<my:DataGridTemplateColumn
CanUserResize="False"
Width="150"
Header="{Binding MeetingName, Source={StaticResource LocStrings}}"
SortMemberPath="MeetingName">
</my:DataGridTemplateColumn>
I have the above column in a Silverlight grid control. But it is giving me a XamlParser error because of how I am trying to set the Header property. Has anyone done this before? I want to do this for multiple languages.
Also my syntax for the binding to a resouce is correct because I tried it in a lable outside of the grid.
You can't Bind to Header because it's not a FrameworkElement. You can make the text dynamic by modifying the Header Template like this:
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
xmlns:dataprimitives="clr-namespace:System.Windows.Controls.Primitives;assembly=System.Windows.Controls.Data"
<data:DataGridTemplateColumn>
<data:DataGridTemplateColumn.HeaderStyle>
<Style TargetType="dataprimitives:DataGridColumnHeader">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<TextBlock Text="{Binding MeetingName, Source={StaticResource LocStrings}}" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</data:DataGridTemplateColumn.HeaderStyle>
</data:DataGridTemplateColumn>
My workaround was to use an attached property to set the binding automatically:
public static class DataGridColumnHelper
{
public static readonly DependencyProperty HeaderBindingProperty = DependencyProperty.RegisterAttached(
"HeaderBinding",
typeof(object),
typeof(DataGridColumnHelper),
new PropertyMetadata(null, DataGridColumnHelper.HeaderBinding_PropertyChanged));
public static object GetHeaderBinding(DependencyObject source)
{
return (object)source.GetValue(DataGridColumnHelper.HeaderBindingProperty);
}
public static void SetHeaderBinding(DependencyObject target, object value)
{
target.SetValue(DataGridColumnHelper.HeaderBindingProperty, value);
}
private static void HeaderBinding_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
DataGridColumn column = d as DataGridColumn;
if (column == null) { return; }
column.Header = e.NewValue;
}
}
Then, in the XAML:
<data:DataGridTextColumn util:DataGridColumnHelper.HeaderBinding="{Binding MeetingName, Source={StaticResource LocStrings}}" />
To keep the visual styling from the original header, use ContentTemplate instead of Template:
<Setter Property="ContentTemplate">
<Setter.Value>
<DataTemplate>
<Image Source="<image url goes here>"/>
</DataTemplate>
</Setter.Value>
Found an interesting workaround that also works with the wpflocalizeaddin.codeplex.com:
Created by Slyi
It uses an IValueConverter
:
public class BindingConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value.GetType().Name == "Binding")
{
ContentControl cc = new ContentControl();
cc.SetBinding(ContentControl.ContentProperty, value as Binding);
return cc;
}
else return value;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return null;
}
}
And a style for the DataGridColumnHeader
<UserControl.Resources>
<local:BindingConverter x:Key="BindCon"/>
<Style x:Key="ColBinding" TargetType="dataprimitives:DataGridColumnHeader" >
<Setter Property="ContentTemplate" >
<Setter.Value>
<DataTemplate>
<ContentPresenter Content="{Binding Converter={StaticResource BindCon}}" />
</DataTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
so that you can keep your favorite binding syntax on the Header
attribute
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel>
<TextBox Text="binding header" x:Name="tbox" />
<data:DataGrid ItemsSource="{Binding AllPeople,Source={StaticResource folks}}" AutoGenerateColumns="False" ColumnHeaderStyle="{StaticResource ColBinding}" >
<data:DataGrid.Columns>
<data:DataGridTextColumn Binding="{Binding ID}"
Header="{Binding Text, ElementName=tbox}" />
<data:DataGridTextColumn Binding="{Binding Name}"
Header="hello" />
</data:DataGrid.Columns>
</data:DataGrid>
</StackPanel>
</Grid>
http://cid-289eaf995528b9fd.skydrive.live.com/self.aspx/Public/HeaderBinding.zip
It does seem much simpler to set the value in code, as mentioned above:
dg1.Columns[3].Header = SomeDynamicValue;
Avoids using the Setter Property syntax, which in my case seemed to mess up the styling, even though I did try using ContentTemplate as well as Template.
One point I slipped up on was that it is better to use the
dg1.Columns[3].Header
notation rather than trying to reference a named column.
I had named one of my columns and tried to reference that in code but got null exceptions. Using the Columns[index] method worked well, and I could assign the Header a text string based on localization resources.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With