2008-09-30 10 views
29
<my:DataGridTemplateColumn 
      CanUserResize="False" 
      Width="150" 
      Header="{Binding MeetingName, Source={StaticResource LocStrings}}" 
      SortMemberPath="MeetingName"> 
    </my:DataGridTemplateColumn> 

J'ai la colonne ci-dessus dans un contrôle de grille Silverlight. Mais il me donne une erreur XamlParser en raison de la façon dont j'essaie de définir la propriété Header. Est-ce que quelqu'un a déjà fait ça? Je veux le faire pour plusieurs langues.Définition dynamique du texte d'en-tête d'une colonne SilverGear DataGrid

Aussi ma syntaxe pour la liaison à une ressource est correcte parce que je l'ai essayé dans un lable en dehors de la grille.

Répondre

28

Vous ne pouvez pas être lié à l'en-tête car ce n'est pas un objet FrameworkElement. Vous pouvez rendre le texte dynamique en modifiant le modèle en-tête comme ceci:

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> 
+0

Grande réponse et merci l'exemple de code – Kyle

+12

Comment gardez-vous le style visuel de l'en-tête d'origine? –

+0

Merci pour la réponse. Vous avez beaucoup aidé. –

1

Pourquoi ne pas tout simplement mis dans votre code:

dg1.Columns[3].Header = SomeDynamicValue; 
0

J'obtenu une solution pour la liaison. Puisque vous utilisez DataGridTemlateColumn, sous-classez-le et ajoutez une propriété de type Binding nommée par exemple "HeaderBinding". Vous pouvez maintenant vous lier à cette propriété à partir du code XAML. Ensuite, vous devez propager la liaison au TextBlock dans le DataTemplate de votre en-tête. Par exemple, vous pouvez le faire avec l'événement OnLoaded de ce TextBlock.

HeaderTextBlock.SetBinding(TextBlock.TextProperty, HeaderBinding); 

C'est tout. Si vous avez plus de colonnes et que vous voulez utiliser un seul DataTemplate, c'est un peu plus compliqué, mais l'idée est la même.

11

Pour garder le style visuel de l'en-tête d'origine, utilisez ContentTemplate au lieu de modèle:

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

+0

Impossible d'obtenir une liaison pour travailler dans le DataTemplate sur un TextBlock: remplace l'image dans votre exemple. – ptoinson

+0

Cela n'aide pas à garder le style visuel dans mon expérience. –

+5

Cette méthode est certainement la voie à suivre, et elle garde le style visuel. Si vous re-template l'en-tête entier, il devient une boîte blanche contenant tout ce que vous mettez là. Toutefois, si vous utilisez un ContentTemplate, l'arrière-plan existant du style d'en-tête par défaut est conservé. – RobSiklos

2

trouvé une solution intéressante qui fonctionne aussi avec le wpflocalizeaddin.codeplex.com:

Créé par Slyi

Il utilise un 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; 
    } 
} 

Et un style pour le 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> 

afin que vous puissiez garder votre syntaxe de liaison préférée sur le Header attribut

<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

13

Ma solution était d'utiliser un propriété jointe pour définir la liaison automatiquement:

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

Puis, dans le XAML:

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

C'est exactement ce que je cherchais, thx. – HolaJan

+1

Contrairement à la solution acceptée, cette solution peut faire ce que la solution acceptée fait en préservant le style original. Ça marche pour moi. +1 –

+0

Cela fonctionne pour moi aussi. C'est absolument PARFAIT, et ce que je cherche: le style et le code derrière, séparés en tant que concepts, séparés en XAML. Merci beaucoup, cela devrait être la solution acceptée. – Sandrous

2

Il ne semble beaucoup plus simple de définir la valeur dans le code, comme mentionné ci-dessus:

dg1.Columns[3].Header = SomeDynamicValue; 

Évite en utilisant la Setter syntaxe de la propriété, ce qui dans mon cas semblait déranger le style, même si j'ai essayé d'utiliser ContentTemplate ainsi que Template.

Un point sur lequel j'ai glissé, c'est qu'il est préférable d'utiliser la notation dg1.Columns[3].Header plutôt que d'essayer de référencer une colonne nommée.

J'avais nommé l'une de mes colonnes et j'ai essayé de faire référence à cela dans le code mais j'ai obtenu des exceptions nulles. L'utilisation de la méthode Columns [index] a bien fonctionné et j'ai pu attribuer à l'en-tête une chaîne de texte basée sur les ressources de localisation.

1

S'il vous plaît noter dans la solution fournie par RobSiklos, Source {...} StaticResource est la clé, si vous envisagez de passer le RelativeSource comme

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

il ne peut pas travailler

Questions connexes