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

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

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

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


person Kyle    schedule 30.09.2008    source источник


Ответы (8)


Вы не можете выполнить привязку к заголовку, потому что это не 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>
person Adam Kinney    schedule 30.09.2008
comment
Как сохранить визуальный стиль исходного заголовка? - person Edward Brey; 31.03.2010
comment
Спасибо за ответ. Вы очень помогли. - person Rob Vermeulen; 15.06.2010
comment
Это тоже помогло мне. Я смог применить его к DataGridTextColumn практически таким же образом. Я использовал также упомянутое предложение ContentTemplate. - person Steve Wranovsky; 07.07.2011
comment
В этом вопросе решение, предоставленное RobSiklos, также сохраняет визуальный стиль. - person Y P; 29.10.2012
comment
Я думаю, что принятый ответ должен быть ответом Роба Сиклоса. Не только потому, что сохраняет визуальный стиль, но и потому, что обеспечивает простую реализацию, разделяющую концепции стиля и кода. - person Sandrous; 04.03.2014

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

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}}" />
person RobSiklos    schedule 29.04.2011
comment
В отличие от принятого решения, это решение может делать то же, что и принятое, плюс сохранять исходный стиль. У меня это работает. +1 - person Y P; 29.10.2012
comment
У меня это тоже работает. Это абсолютно ИДЕАЛЬНО, и то, что я ищу: стиль и код, разделенные как концепции, разделенные в XAML. Большое спасибо, это должно быть приемлемое решение. - person Sandrous; 04.03.2014
comment
Нравится это решение больше, так как оно сохраняет ответственность и разделение проблем. - person Pingi; 03.01.2016

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

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

person Lars Holm Jensen    schedule 02.09.2010
comment
Кажется, не удается получить привязку для работы в DataTemplate на TextBlock: ‹TextBlock Text = {Binding HeaderText} /› заменяет изображение в вашем примере. - person ptoinson; 20.10.2010
comment
По моему опыту, это не помогает сохранить визуальный стиль. - person Steven Oxley; 11.11.2010
comment
Этот метод определенно лучший, и он ДЕЙСТВИТЕЛЬНО сохраняет визуальный стиль. Если вы повторно шаблонизируете весь заголовок, он превратится в белое поле, содержащее все, что вы туда поместили. Однако при использовании ContentTemplate существующий фон стиля заголовка по умолчанию сохраняется. - person RobSiklos; 29.04.2011
comment
Кроме того, если вы укажете Источник привязки как некоторый StaticResource (как в исходном сообщении), он будет работать. - person RobSiklos; 29.04.2011

Нашел интересный обходной путь, который также работает с 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

person Rudi    schedule 09.03.2011

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

dg1.Columns[3].Header = SomeDynamicValue;

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

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

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

person Steve    schedule 11.11.2011

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

dg1.Columns[3].Header = SomeDynamicValue;
person Jersey Dude    schedule 05.02.2010

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

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

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

person Jit    schedule 16.08.2013

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

 HeaderTextBlock.SetBinding(TextBlock.TextProperty, HeaderBinding);

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

person Dimitar    schedule 06.04.2010