将ViewModel属性绑定到DataGridComboBoxColum

时间:2013-10-03 09:33:27

标签: wpf datagrid datagridcomboboxcolumn

我正在尝试在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')

1 个答案:

答案 0 :(得分:2)

DataGrid Columns dont come under the visualtree of their parent。这就是为什么they cannot inherit the DataContext来自父母,他们也可以引用祖先。

另一方面,DataGrid行和单元格位于visualtree下,因此可以找到祖先并继承DataContext。

要绑定列,您需要use the BindingProxy

要做到这一点,您可以将窗口资源中的一个资源定义为

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>