Reputation: 74360
After reading the excellent article on how to Customize Auto-Generated Columns, I have come across an issue.
While trying to customize auto-generated columns in a DataGrid
control, I want to do simple things like make sure that all numeric column values are right-aligned. To this end, I created a DataTemplate
as follows:
<DataGrid x:Name="MyGrid" AutoGeneratingColumn="MyGrid_AutoGeneratingColumn">
<DataGrid.Resources>
<DataTemplate x:Key="IntegerTemplate">
<TextBlock Text="{Binding}" HorizontalAlignment="Right"/>
</DataTemplate>
</DataGrid.Resources>
</DataGrid>
Then, in the AutoGeneratingColumn
DataGrid
event handler, I want to assign this generic DataTemplate
as the CellTemplate
for all integral (i.e., numeric) columns:
public void MyWindow_AdjustColumnTemplateBasedOnType(
DataGridAutoGeneratingColumnEventArgs e)
{
if (/*This is a column I want to change*/)
{
DataGridTemplateColumn column=new DataGridTemplateColumn();
column.Header=e.PropertyName;
column.CellTemplate=MyGrid.FindResource("IntegerTemplate") as DataTemplate;
e.Column=column;
}
}
The problem is that the value of the Text
column of the TextBlock
does not display the desired results. Instead of seeing the right justified value in each cell whose column has this DataTemplate
as its CellTemplate
, I see:
Using the empty binding syntax by setting the attribute Text
to "{Binding}"
is obviously incorrect. Setting a path based binding does produce the desired result. That is, if I set a (hard-coded data path) binding using something like:
<DataGrid.Resources>
<DataTemplate x:Key="IntegerTemplate">
<!-- Binding hard set to ProductId -->
<TextBlock Text="{Binding ProductId}" HorizontalAlignment="Right"/>
</DataTemplate>
</DataGrid.Resources>
Then all is well, but my generic DataTemplate
is no longer generic. Instead of it being reusable for all integer columns, it can only be used for the ProductId
column, because the binding is fixed to the value of that specific data item:
What is the correct binding I should use so that the generic DataTemplate
actually uses whatever value is in the corresponding ItemSource
property for the column with which it is associated.
Upvotes: 4
Views: 9097
Reputation: 11
For people struggling with the "What is the correct binding I should use so that the generic DataTemplate actually uses whatever value is in the corresponding ItemSource property for the column with which it is associated."
See Jay_Wang's answer in this link:
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/8b2e94b7-3c44-4642-8acc-851de5285062
The important bit is overriding the System.Windows.FrameworkElement GenerateElement function so that it can programatically set up the binding to use the column name.
Hope this helps.
Upvotes: 1
Reputation: 61
I believe styles will solve your issue here .
private void MyGrid_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
if (/*This is a column I want to change*/)
{
DataGridColumn column = e.Column;
column.CellStyle = MyGrid.FindResource("IntegerTemplate") as Style;
}
}
and in XAML you can write
<Style TargetType="DataGridCell" x:Key="IntegerTemplate">
<Setter Property="FontWeight" Value="Bold"></Setter>
</Style>
Upvotes: 6
Reputation: 5886
When using a TemplateColumn in a DataGrid context you usually have to use a ValueConverter as well.
This ValueConverter converts the data from you ViewModels object (which is in fact the reason why you want to use a TemplateColum instead of an ordinary TextColumn) to an representable string form.
Do you have such a converter or do you provide a ToString() method in your ViewModels object ? If not try it, maybe that helps ...
Upvotes: 1