将 WPF DataGridComboBoxColumn 与 MVVM 结合使用 - 绑定到 ViewModel 中的属性 [英] Using WPF DataGridComboBoxColumn with MVVM - Binding to Property in ViewModel

查看:46
本文介绍了将 WPF DataGridComboBoxColumn 与 MVVM 结合使用 - 绑定到 ViewModel 中的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用出色的 MVVM Light Toolkit.我的 ViewModel 公开:

I'm using the excellent MVVM Light Toolkit. My ViewModel exposes:

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);
    }
}

视图有一个 DataGrid:

The View has a 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>

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

The DataGrid has an ItemsSource, as you can see, of CourtCodes. I want the CourtType column to be a drop down of all enumerated CourtTypes that are contained within CourtCodesTypeCourt. For the life of me, I can't seem to populate the DataGridComboBoxColumn with anything. The current failed attempt is looking to use RelativeSource... what am I doing wrong?

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

In addition to not working, the two errors I see are:

System.Windows.Data 错误:4:不能查找绑定参考源'RelativeSource FindAncestor,AncestorType='System.Windows.Window',AncestorLevel='1''.BindingExpression:Path=DataContext.CourtCodesTypeCourt;数据项=空;目标元素是'DataGridComboBoxColumn'(哈希码=38771709);目标财产是ItemsSource"(类型IEnumerable")

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

System.Windows.Data 错误:40:BindingExpression 路径错误:'CourtCodesTypeCourt' 属性不是在 'object' ''Court' 上找到(HashCode=38141773)'.BindingExpression:Path=CourtCodesTypeCourt.CourtTypeDescription;DataItem='Court' (HashCode=38141773);目标元素是组合框"(姓名='');目标属性是文本"(输入'字符串')

System.Windows.Data Error: 40 : BindingExpression path error: 'CourtCodesTypeCourt' property not found on 'object' ''Court' (HashCode=38141773)'. BindingExpression:Path=CourtCodesTypeCourt.CourtTypeDescription; DataItem='Court' (HashCode=38141773); target element is 'ComboBox' (Name=''); target property is 'Text' (type 'String')

推荐答案

DataGrid 列定义没有以您期望的方式参与逻辑树.这很荒谬,但最后我检查过你必须做这样的事情:

DataGrid column definitions don't participate in the logical tree in the way you would expect. It's ridiculous, but last I checked you have to do something like this:

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

您会注意到我还将您的 TextBinding 更改为 SelectedItemBinding.我不确定您是否真的想要 TextBinding,但如果您只想允许用户在列表之间进行选择,那么 SelectedItemBinding 可能就是您想要的.

You'll notice I've also changed your TextBinding to a SelectedItemBinding. I'm not sure if you actually intended a TextBinding, but if you just want to allow the user to select between the list, then SelectedItemBinding is likely what you want.

此外,您的虚拟机并没有完全遵循最佳实践.您正在使用 List 而不是 ObservableCollection,并且您将其公开为 List 而不是某些东西更简单的比如ICollection.

Also, your VMs don't exactly follow best practices. You're using List<T> instead of ObservableCollection<T>, and you're exposing it as List<T> rather than something simpler such as ICollection<T>.

这篇关于将 WPF DataGridComboBoxColumn 与 MVVM 结合使用 - 绑定到 ViewModel 中的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆