Подтвердить что ты не робот

Динамическая настройка текста заголовка столбца Silverlight DataGrid

  <my:DataGridTemplateColumn 
            CanUserResize="False" 
            Width="150" 
            Header="{Binding MeetingName, Source={StaticResource LocStrings}}" 
            SortMemberPath="MeetingName"> 
  </my:DataGridTemplateColumn>

У меня есть столбец выше в элементе управления Silverlight. Но это дает мне ошибку XamlParser из-за того, как я пытаюсь установить свойство заголовка. Кто-нибудь делал это раньше? Я хочу сделать это для нескольких языков.

Также мой синтаксис для привязки к resouce правильный, потому что я попробовал его в макете вне сетки.

4b9b3361

Ответ 1

Вы не можете привязать к заголовку, потому что это не элемент FrameworkElement. Вы можете сделать текст динамическим, изменив шаблон заголовка следующим образом:

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>

Ответ 2

Мое обходное решение заключалось в том, чтобы использовать прикрепленное свойство, чтобы автоматически установить привязку:

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;
    }
}

Затем в XAML:

<data:DataGridTextColumn util:DataGridColumnHelper.HeaderBinding="{Binding MeetingName, Source={StaticResource LocStrings}}" />

Ответ 3

Чтобы сохранить визуальный стиль из исходного заголовка, используйте ContentTemplate вместо Template:

<Setter Property="ContentTemplate">
<Setter.Value>
    <DataTemplate>
        <Image Source="<image url goes here>"/>
    </DataTemplate>
</Setter.Value>

Ответ 4

Обнаружено интересное обходное решение, которое также работает с wpflocalizeaddin.codeplex.com:

Создано Slyi

Он использует 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;
    }
}

И стиль для 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>

чтобы сохранить свой любимый синтаксис привязки в атрибуте Header

<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

Ответ 5

Кажется намного проще установить значение в коде, как указано выше:

dg1.Columns[3].Header = SomeDynamicValue;

Избегает использования синтаксиса свойства Setter, который в моем случае, казалось, испортил стилизацию, хотя я и попытался использовать ContentTemplate, а также Template.

Один момент, на который я поднялся, - это то, что лучше использовать dg1.Columns[3].Header вместо того, чтобы пытаться ссылаться на именованный столбец.

Я назвал один из моих столбцов и попытался ссылаться на это в коде, но получил нулевые исключения. Использование метода Columns [index] хорошо работает, и я могу назначить Header текстовую строку на основе ресурсов локализации.

Ответ 6

Почему бы просто не установить это в коде:

dg1.Columns[3].Header = SomeDynamicValue;

Ответ 7

Обратите внимание, что в решении, предоставленном RobSiklos, Source {staticResource...} - это ключ, если вы планируете передать RelativeSource, например

Binding DataContext.SelectedHistoryTypeItem,RelativeSource={RelativeSource AncestorType=sdk:DataGrid},

он может не работать

Ответ 8

У меня есть решение для привязки. Поскольку вы используете DataGridTemlateColumn, подклассируйте его и добавьте свойство типа Binding, названное по имени "HeaderBinding". Теперь вы можете связать это свойство с XAML. Затем вы должны распространять привязку к TextBlock в DataTemplate вашего заголовка. Например, вы можете сделать это с событием OnLoaded этого TextBlock.

 HeaderTextBlock.SetBinding(TextBlock.TextProperty, HeaderBinding);

Что это. Если у вас больше столбцов и вы хотите использовать только один DataTemplate, это немного сложнее, но идея одинаков.