WPF DataGridTextColumn Tooltip - wpf

Is there a way to add tool tip to DataGridColumn header and still retain the sorting functionality. The below code doesnt work(It doesnt display the tooltip)
<toolkit:DataGridTextColumn Header="Test" Width="70" Binding="{Binding TestText}" ToolTipService.ToolTip="{Binding TestText}">
And when I use the code below
<toolkit:DataGridTemplateColumn Header="Test" Width="70">
<toolkit:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding TestText}" ToolTip="{Binding TestText}" />
</DataTemplate>
</toolkit:DataGridTemplateColumn.CellTemplate>
</toolkit:DataGridTemplateColumn>
The column loses sorting functionality..Help!

To get the ToolTip to display in the DataGridColumnHeader you'll need to bind the ToolTip property for it to the ToolTip of its DataGridColumn like this
<toolkit:DataGridTextColumn Header="Test"
Width="70"
Binding="{Binding TestText}"
ToolTipService.ToolTip="My Tooltip Text">
<toolkit:DataGridTextColumn.HeaderStyle>
<Style TargetType="toolkit:DataGridColumnHeader">
<Setter Property="ToolTip"
Value="{Binding RelativeSource={RelativeSource Self},
Path=Column.(ToolTipService.ToolTip)}"/>
</Style>
</toolkit:DataGridTextColumn.HeaderStyle>
</toolkit:DataGridTextColumn>

When the grid creates automatic columns, it knows which field is being displayed in that column. When you create the column yourself, the data grid doesn't know what data you'll be displaying in that column and so it cannot guess which field to sort the column by.
To make a column you define yourself sortable, add the SortMemberPath property to your DataGridTemplateColumn like this:
<DataGridTemplateColumn Header="Test" Width="70" SortMemberPath="TestText">
...
</DataGridTemplateColumn>

Previous answers are mostly correct, however I find them overly complicated or addressing only one of the two concerns of the post.
Firstly, you can always set the SortPath property to maintain sorting for a DataGridTemplateColumn, or possibly when you want to sort on some property other than what is displayed.
Second, you do not need a DataGridTemplateColumn in order to have a ToolTip on the Column Header like the OP mentions. You might use a template column if you want to add a tooltip to the actual cell (but this probably isn't needed either). In any case, adding a ToolTip to the column header is most easily accomplished by the HeaderStyle
<DataGridTextColumn Header="Test" Binding="{Binding TestText}">
<DataGridTextColumn.HeaderStyle>
<Style TargetType="DataGridColumnHeader">
<Setter Property="ToolTip" Value="Test ToolTip" />
</Style>
</DataGridTextColumn.HeaderStyle>
</DataGridTextColumn>

You are adding a tooltip to the column template, not to the header.
Have you tried setting the HeaderStyle property on DataGridColumn to a style that contains a template including a tooltip for the HeaderCell?
Have a look at this example too

Related

Is it possible to parameterize the binding on a DataGrid CellTemplate in a resource?

I'm putting together some generic CellTemplate styles for a WPF grid (WPFToolKit DataGrid), and I’m not sure of the syntax to use to make the binding generic. So for example, I have this template, which turns the value red if the value is negative:
<DataTemplate x:Key="RedNegativeCellTemplate">
<TextBlock Name="QuantityTextBox" Text="{Binding Quantity, StringFormat='c', Mode=OneWay}"/>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding Quantity, Converter={StaticResource SignConverter}}" Value="-1">
<Setter TargetName="QuantityTextBox" Property="Foreground" Value="Red"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
You’ll notice that this has a binding on the Text box to the column value ‘Quantity’ - i.e., the field/column that the binding comes from is explicit.
So I can use this in my WPF DataGrid as follows:
<sdk:DataGrid ItemsSource="{Binding MyDataSource}" AutoGenerateColumns="False">
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="Net Quantity" CellTemplate="{StaticResource RedNegativeCellTemplate}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
But… what I’d really like to do is to have the field binding generic for the template, so that I can re-use the template as follows:
<sdk:DataGrid ItemsSource="{Binding OrdersQuery}"AutoGenerateColumns="False">
<sdk:DataGrid.Columns>
<sdk:DataGridTemplateColumn Header="Quantity" CellTemplate="{StaticResource RedNegativeCellTemplate}"/>
<sdk:DataGridTemplateColumn Header="Price" CellTemplate="{StaticResource RedNegativeCellTemplate}"/>
<sdk:DataGridTemplateColumn Header="Total" CellTemplate="{StaticResource RedNegativeCellTemplate}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
Now, the problem here is that there doesn't seem to be a way to parameterize the binding in the CellTemplate. But I'm loath to have to have 3+ lines of controltemplate for every column that uses this template, as it clutters the XAML and makes it far less readable (not to mention the fact that if I decide to change the cell template to put a border around the textbox, I'd have to modify it in multiple places.
So I'm thinking that the binding within the CellTemplate should look something like this (note that we're using '.' for the binding path):
Text="{Binding Path=., StringFormat='c', Mode=OneWay}"
And then somehow set the datacontext from the DataGridTemplateColumn declaration – but I can’t see how to do it.
Any idea how to do this?
#Webreaper: If I understand your idea correctly, then you and I are running into the same stuff. I haven't tried my version of the solution, basically, I will bind the path property of a binding to the DataGridTemplateColumn's SortMemberPath.
<DataGrid>
....
<DataGridTemplateColumn CellTemplate={StaticResource CellTemplateKey} />
....
</DataGrid>
Where CellTemplateKey is defined somewhere (in App.xaml, for example):
<DataTemplate x:Key="CellTemplateKey">
<TextBlock Binding="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridRow}, Path={Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridTemplateColumn, Path=SortMemberPath}}}}" />
</DataTemplate>
I'll check and update this later. I hope the idea is helpful somehow. I may look into Dyna
For this you can use DataTemplateSelector which is actually pretty straightforward to implement.
If you need some further explanations and examples - let me know.

DataTrigger on DataGridTextColumn

I am trying to attach a datatrigger on one of my combobox element. The trigger should read the attached property of the DataGridTextColumn (combobox's ancestor) and take decision based on that. Now the problem is that the DataGridTextColumn isn't part of Visual Tree so I cannot get it by RelativeSource Ancestor. Here is sample code.
<ComboBox Name="cmbFilter" DisplayMemberPath="CategoryName">
<ComboBox.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type DataGridTextColumn}},
Path=Header}"
Value="Id">
<Setter Property="Control.Visibility" Value="Collapsed"/>
</DataTrigger>
</Style.Triggers>
</Style>
</ComboBox.Style>
</ComboBox>
Any one maybe suggest some alternative
Edit:
#denis
I don't really understand your solution, so let me explain in detail. I am developing a general purpose filter that would apply to all DataGrid's that need the filtering functionality. The DataGrid definition will specify whether it wants filtering or not by specifying custom attached property "IsFilterable" on DataGrid. Individual DataGridColum will specify what kind of filter they want (combobox or textbox) by specifying "FilterDisplayType" on DataGridColumn. The DataGrid will know nothing other than above. All the functionality will then be handled by the Filter based on the above attached properties on DataGrid and DataGridColumn (all types of columns).
My point in my comment was that, you can trigger on a property that you bind to, not on the header.. Because if you respond to a header change, than you have to trigger the header, which is fine, but that can be the exact same Property on your model that you respond to, only in a diff place.
Also you can't put a combo box in DataGridTextColumn,
So you'd have to either:
<DataGridComboBoxColumn ItemsSource="{Binding CategoryNameItems}"
DisplayMemberPath="{Binding CategoryName}"
Visibility="{Binding MyVisibilityProperty, Converter={StaticResource BoolToVisibility}}" />
Which will hide the whole column or to hide only the combobox put it in the CellTemplate:
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding CategoryNameItems}" DisplayMemberPath="{Binding CategoryName}"
Visibility="{Binding MyVisibilityProperty, Converter={StaticResource BoolToVisibility}}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

DataGrid column header text wrapping in silverlight

I am using a DataGrid in my silverlight project and I want one column to wrap it's header text. I know using a style for the header might be the answer but I want to know if there is a wrap property for a datagrid column header?
Here is my code:
<data:DataGrid x:Name="gridViewResources"
AutoGenerateColumns="False"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ItemsSource="{Binding OpportunityResourceDetailList, Mode=TwoWay}" IsReadOnly="True">
<data:DataGrid.Columns>
<data:DataGridTemplateColumn Header="#" Width="Auto">
<data:DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding PositionLevel.FullPositionAndLevelName}" />
</DataTemplate>
</data:DataGridTemplateColumn.CellTemplate>
</data:DataGridTemplateColumn>
Thanks!
I haven't found a way to get Silverlight to automatically wrap the header (in much the same way as the TextWrapping property of a TextBlock does). I suspect that it's not possible due to a limitation of the DataGridColumn.Header property:
Use discretion when using objects as header content; not all Silverlight objects are suitable for use within the limited presentation surface that appears for headers.
However, you can 'manually' wrap header text. If you put a newline in the header text, the header text will be broken over two lines at that point. (In XAML, you use the character entity
.) For example, the following header text appears split over three lines:
<sdk:DataGridTextColumn Header="ABCD
EFGH
IJKL" />
There is no specific property on a DataGridColumn to support this but once you have created the right style it is just as easy - simply set the HeaderStyle property for the specific column.
Create a Style resource with a TargetType of DataGridColumnHeader and set the ContentTemplate property to be a DataTemplate containing a TextBlock with the TextWrapping property set to Wrap. I've enclosed the TextBlock within a Grid panel to keep this closer to the default DataTemplate used by the ContentPresenter. Apply this style to a specific column using the HeaderStyle property or to the whole DataGrid using the ColumnHeaderStyle property.
Note that you will need to constrain the width of the Column to something less than the header text for the wrapping to take affect unless you specifically restrict the width of the TextBlock in the DataTemplate.
<Style x:Key="CustomDataGridColumnHeaderStyle" TargetType="sdk:DataGridColumnHeader" BasedOn="{StaticResource DefaultDataGridColumnHeaderStyle}">
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Grid>
<TextBlock Text="{Binding}" TextWrapping="Wrap" />
</Grid>
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
...
<sdk:DataGrid >
<sdk:DataGrid.Columns>
<sdk:DataGridTextColumn Header="Header Name" Binding="{Binding Xxx}" Width="80" HeaderStyle="{StaticResource CustomDataGridColumnHeaderStyle}"/>
</sdk:DataGrid.Columns>
</sdk:DataGrid>
here is my code
<DataGrid.ColumnHeaderStyle>
<Style TargetType="ContentControl">
<Setter Property="HorizontalContentAlignment" Value="Center"></Setter>
<Setter Property="ContentTemplate" >
<Setter.Value >
<DataTemplate>
<TextBlock Text="{Binding}" TextWrapping="Wrap" FontWeight="Bold" TextAlignment="Center" LineHeight="20"></TextBlock></DataTemplate>
</Setter.Value>
</Setter>
</Style>
`enter code here`</DataGrid.ColumnHeaderStyle>

Applying TextDecoration to an WPF ListViewItem

I can see how to apply a text decoration to a GridViewColumn.
<GridViewColumn Header="Tool" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Entity.ToolId}" TextDecorations="{Binding Path=TextDecoration}" />
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
But if I want the TextDecoration to apply to the entire row (in my case a strikethrough), then I have to duplicate the above code to every GridViewColumn.
What I can not figure out is how to apply the TextDecoration to the entire listview item possibly via the ItemContainerStyle.
Can anyone give me a head up on how this could be done?
You should not define the binding per column, if the cells of each column support TextDecoration, because then you need to repeat it for every column. Better apply it to DataGrid.CellStyle property:
<DataGrid.CellStyle>
<Style TargetType="TextBlock">
<Setter Property="TextDecorations"
Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}},
Path =Item.TextDecoration}" />
</Style>
</DataGrid.CellStyle>
The challenge here is to access the property TextDecoration. Use relative source binding to find the parent DataGridRow which has an Item property which contains the data for that row.
Formatting WPF DataGrid using binding can be rather perplexing. See my article on CodeProject where I cover the most important cases, including applying TextDecoration on single cells (or all cells in your case): Guide to WPF DataGrid Formatting Using Bindings
use GridViewRow.CellTemplate

Styling columns based on DataGridTemplateColumn in a WPF DataGrid

I am using a WPF DataGrid where one of the columns has a requirement to show an "Edit" hyperlink if the row is editable - this is indicated by a boolean flag in the backing model for the row. I was able to achieve this using a DataGridTemplateColumn - no problems. However an additional requirement on the entire row is not to show any highlights when the row is selected (this is a blue background by default). I have been able to achieve this on other columns by defining the DataGridCell style with a transparent background, e.g.
<DataGridTextColumn
Header="Id"
Binding="{Binding Path=Id}"
HeaderStyle="{StaticResource DataGridColumnHeaderStyle}"
CellStyle="{StaticResource DataGridCellStyle}" />
where DataGridCellStyle is defined as follows:
<Style x:Key="DataGridCellStyle" TargetType="{x:Type DataGridCell}">
<Setter Property="Background" Value="Transparent" />
...
</Style>
However the column in question, a DataGridTemplateColumn, does not offer a "CellStyle" attribute which I can use for turning off selection highlights. So my question is how to set the cell style when using a DataGridTemplateColumn? Here's my implementation of the column which satisfies the first requirement (i.e. showing an "Edit" hyperlink if the row is editable):
<DataGridTemplateColumn
Header="Actions"
HeaderStyle="{StaticResource CenterAlignedColumnHeaderStyle}">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock
Visibility="{Binding Path=Editable, Converter={StaticResource convVisibility}}"
Style="{StaticResource CenterAlignedElementStyle}">
<Hyperlink
Command="..."
CommandParameter="{Binding}">
<TextBlock Text="Edit" />
</Hyperlink>
</TextBlock>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Thanks.
At least in WPF4, there is a CellStyle for DataGridTemplateColumns: http://msdn.microsoft.com/en-us/library/cc189163.aspx

Resources