web-dev-qa-db-ja.com

SilverlightDataGrid列のヘッダーテキストを動的に設定する

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

上記の列がSilverlightグリッドコントロールにあります。しかし、Headerプロパティを設定しようとしているため、XamlParserエラーが発生します。誰かが以前にこれをしたことがありますか?複数の言語でこれを実行したいと思います。

また、グリッドの外側のラベルで試したため、リソースへのバインドの構文は正しいです。

29
Kyle

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>
28
Adam Kinney

私の回避策は、添付プロパティを使用してバインディングを自動的に設定することでした。

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}}" />
14
RobSiklos

元のヘッダーの視覚的なスタイルを維持するには、テンプレートの代わりにContentTemplateを使用します。

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

上記のように、コードで値を設定する方がはるかに簡単なようです。

dg1.Columns[3].Header = SomeDynamicValue;

TemplateだけでなくContentTemplateも使用しようとしたにもかかわらず、私の場合はスタイルを台無しにしているように見えるSetterProperty構文の使用を避けます。

私が気づかなかった1つのポイントは、名前付きの列を参照するよりも、dg1.Columns[3].Header表記を使用する方がよいということでした。

列の1つに名前を付け、コードでそれを参照しようとしましたが、null例外が発生しました。 Columns [index]メソッドを使用するとうまく機能し、ローカリゼーションリソースに基づいてヘッダーにテキスト文字列を割り当てることができました。

2
Steve

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

2
Rudi

これをコードで単純に設定してみませんか?

dg1.Columns[3].Header = SomeDynamicValue;
1
Jersey Dude

RobSiklosが提供するソリューションでは、RelativeSourceを次のように渡す場合は、ソース{staticResource ...}がキーであることに注意してください。

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

動作しない可能性があります

1
Jit

バインディングの解決策がありました。 DataGridTemlateColumnを使用するため、サブクラス化して、たとえば「HeaderBinding」という名前のBindingタイプのプロパティを追加します。これで、XAMLからそのプロパティにバインドできます。次に、ヘッダーのDataTemplateでTextBlockへのバインディングを伝播する必要があります。たとえば、そのTextBlockのOnLoadedイベントでそれを行うことができます。

 HeaderTextBlock.SetBinding(TextBlock.TextProperty, HeaderBinding);

それでおしまい。より多くの列があり、1つのDataTemplateのみを使用する場合は、少し複雑になりますが、考え方は同じです。

0
Dimitar