0

Datagrid で列挙型を使用しようとしています。それが機能する2つの方法を紹介しましょう。まず、DataGrid 内に ComboBox を作成します。DataContext.MyOptions は、列挙型のすべての値に対して文字列のリストを返します。

<DataGridTemplateColumn Header="Enum1">
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <ComboBox ItemsSource="{Binding DataContext.MyOptions, RelativeSource={RelativeSource AncestorType=Window}}" 
                      SelectedItem="{Binding Enum1, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource MyConverter}}" />
        </DataTemplate>
    </DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>

次に、DataGridComboBoxColumn を使用しようとしていますが、これを機能させるには、ElementStyle と EditingElementStyle を追加する必要があります (どこかからコピーしました)。

<DataGridComboBoxColumn Header="Enum1" Width="*" 
                        SelectedItemBinding="{Binding Enum1, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource MyConverter}}">
    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding Path=DataContext.MyOptions, RelativeSource={RelativeSource AncestorType=Window}}" />
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding Path=DataContext.MyOptions, RelativeSource={RelativeSource AncestorType=Window}}" />
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>

</DataGridComboBoxColumn>

私の質問は、なぜ以下が機能しないのかということです。列は空ですが、値はあります。

<DataGridComboBoxColumn Header="Enum1" Width="*" 
                        ItemsSource="{Binding Path=DataContext.MyOptions, RelativeSource={RelativeSource AncestorType=Window}}" 
                        SelectedItemBinding="{Binding Enum1, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource MyConverter}}">
</DataGridComboBoxColumn>

出力ウィンドウに次のエラーが表示されます。

System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=DataContext.MyOptions; DataItem=null; target element is 'DataGridComboBoxColumn' (HashCode=59316889); target property is 'ItemsSource' (type 'IEnumerable')
4

1 に答える 1

2

DataGrid Columns dont come under the visualtree of their parent. そのためthey cannot inherit the DataContext、親からも祖先を参照することもできません。

一方、DataGrid の行とセルは visualtree の下にあるため、祖先を見つけて DataContext を継承できます。

列をバインドするには、use the BindingProxy.

それを行うには、ウィンドウ リソースで 1 つのリソースを次のように定義します。

public class BindingProxy : Freezable
{
    #region Overrides of Freezable

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    #endregion

    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Data.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty DataProperty =
        DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null));
}

<DataGrid.Resources>
    <local:BindingProxy x:Key="ProxyElement" Data="{Binding}" />
</DataGrid.Resources>

次に、この要素を使用して列にバインドします

<DataGridComboBoxColumn Header="Enum1" Width="*" 
                        ItemsSource="{Binding Path=Data.MyOptions, Source={StaticResource ProxyElement}" 
                        SelectedItemBinding="{Binding Enum1, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource MyConverter}}">
</DataGridComboBoxColumn>
于 2013-10-03T09:50:34.653 に答える