将WPF DataGridComboBoxColumn与MVVM结合使用 - 绑定到ViewModel中的属性

Mik*_*e L 11 wpf mvvm wpfdatagrid mvvm-light

我正在使用优秀的MVVM Light Toolkit.我的ViewModel公开了:

public const string CourtCodesTypeCourtPropertyName = "CourtCodesTypeCourt";
private List<CourtType> _courtCodesTypes = new List<CourtType>();
public List<CourtType> CourtCodesTypeCourt
{
    get
    {
        return _courtCodesTypes;
    }

    set
    {
        if (_courtCodesTypes == value)
        {
            return;
        }

        var oldValue = _courtCodesTypes;
        _courtCodesTypes = value;

        // Update bindings and broadcast change using GalaSoft.MvvmLight.Messenging
        RaisePropertyChanged(CourtCodesTypeCourtPropertyName, oldValue, value, true);
    }
}

public const string CourtCodesPropertyName = "CourtCodes";
private List<Court> _courtCodes = null;
public List<Court> CourtCodes
{
    get
    {
        return _courtCodes;
    }

    set
    {
        if (_courtCodes == value)
        {
            return;
        }

        var oldValue = _courtCodes;
        _courtCodes = value;

        // Update bindings and broadcast change using GalaSoft.Utility.Messenging
        RaisePropertyChanged(CourtCodesPropertyName, oldValue, value, true);
    }
}
Run Code Online (Sandbox Code Playgroud)

View有一个DataGrid:

<DataGrid
      ItemsSource="{Binding CourtCodes, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
      AutoGenerateColumns="False"
      AlternatingRowBackground="{DynamicResource OffsetBrown}"
      AlternationCount="1" Margin="45,0">
   <DataGrid.Columns>
    <DataGridTextColumn Binding="{Binding Abbreviation, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
         Header="Abbreviation"
         Width="25*" />
    <DataGridTextColumn Binding="{Binding FullName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
         Header="Court"
         Width="75*" />
    <DataGridComboBoxColumn Header="CourtType" 
         ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CourtCodesTypeCourt} TextBinding="{Binding CourtTypeDescription}""/>
   </DataGrid.Columns>
  </DataGrid>
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,DataCrid有一个可以看到CourtCodes的ItemsSource.我希望CourtType列是CourtCodesTypeCourt中包含的所有枚举CourtType的下拉列表.对于我的生活,我似乎无法用任何东西填充DataGridComboBoxColumn.当前失败的尝试正在寻找使用RelativeSource ...我做错了什么?

除了不工作之外,我看到的两个错误是:

System.Windows.Data错误:4:无法找到绑定源,引用'RelativeSource FindAncestor,AncestorType ='System.Windows.Window',AncestorLevel ='1''.BindingExpression:路径= DataContext.CourtCodesTypeCourt; 的DataItem = NULL; target元素是'DataGridComboBoxColumn'(HashCode = 38771709); target属性是'ItemsSource'(输入'IEnumerable')

System.Windows.Data错误:40:BindingExpression路径错误:在'对象'''Court'(HashCode = 38141773)'上找不到'CourtCodesTypeCourt'属性.BindingExpression:路径= CourtCodesTypeCourt.CourtTypeDescription; DataItem ='Court'(HashCode = 38141773); target元素是'ComboBox'(Name =''); target属性是'Text'(类型'String')

Ken*_*art 28

DataGrid列定义不会以您期望的方式参与逻辑树.这太荒谬了,但最后我检查过你必须这样做:

<DataGridComboBoxColumn Header="CourtType" SelectedItemBinding="{Binding Type}">
    <DataGridComboBoxColumn.ElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CourtCodesTypeCourt}"/>
            <Setter Property="IsReadOnly" Value="True"/>
        </Style>
    </DataGridComboBoxColumn.ElementStyle>
    <DataGridComboBoxColumn.EditingElementStyle>
        <Style TargetType="ComboBox">
            <Setter Property="ItemsSource" Value="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=DataContext.CourtCodesTypeCourt}"/>
        </Style>
    </DataGridComboBoxColumn.EditingElementStyle>
</DataGridComboBoxColumn>
Run Code Online (Sandbox Code Playgroud)

你会注意到我也把你改成TextBindingSelectedItemBinding.我不确定你是否真的想要一个TextBinding,但如果你只是想让用户在列表之间进行选择,那么SelectedItemBinding很可能就是你想要的.

此外,您的VM并不完全遵循最佳实践.你正在使用List<T>而不是ObservableCollection<T>,而是将它暴露出来List<T>而不是简单的东西,比如ICollection<T>.