0

我正在尝试在 Datagrid 中使用枚举。让我向您展示它的两种工作方式。首先,我在 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 行和单元格位于可视树下,因此可以找到祖先并继承 DataContext。

为了绑定列,您需要use the BindingProxy.

为此,您可以在 Window Resource 中定义一个资源为

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 回答