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

发布于 2024-09-15 12:51:37 字数 2975 浏览 5 评论 0原文

我正在使用优秀的 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);
    }
}

该视图有一个 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...我做错了什么?

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

System.Windows.Data 错误:4:无法 查找参考绑定源 '相对源查找祖先, AncestorType='System.Windows.Window', 祖先等级='1''。 BindingExpression:Path=DataContext.CourtCodesTypeCourt; 数据项=空;目标元素是 'DataGridComboBox列' (哈希码=38771709);目标财产 是“ItemsSource”(类型“IEnumerable”)

并且

System.Windows.Data 错误:40: BindingExpression路径错误: “CourtCodesTypeCourt”属性不 在“对象”“法庭”上找到 (哈希码=38141773)'。 BindingExpression:Path=CourtCodesTypeCourt.CourtTypeDescription; DataItem='法院'(HashCode=38141773); 目标元素是“ComboBox” (名称='');目标属性是“文本” (输入“字符串”)

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

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>

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

and

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

扛刀软妹 2024-09-22 12:51:37

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>

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

此外,您的虚拟机并不完全遵循最佳实践。您使用的是 List 而不是 ObservableCollection,并且您将其公开为 List 而不是其他东西更简单,例如 ICollection

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>

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.

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

岁月无声 2024-09-22 12:51:37

在这里我找到了答案 http://cinch.codeplex.com/discussions/239522

对于DataGridComboBoxColumn 您必须创建 ItemsSource 的 StaticRecource,如下所示:

<CollectionViewSource Source="{Binding Element=theView, Path=DataContext.ViewModelCollection1}" x:Key="ViewModelCollection1" />

并将其绑定到 DataGridComboBoxColumn,如下所示:

ItemsSource="{Binding Source={StaticResource ViewModelCollection1}}"

那是因为 DataGridColumns 不是可视化树的一部分。

如果您想绑定 DataGrid 的项目集合,则必须在两种样式上设置 ItemsSource:

<DataGridComboBoxColumn.ElementStyle>
    <Style TargetType="ComboBox">
        <Setter Property="ItemsSource" Value="{Binding Path=ModelCollection1}" />
    </Style> </DataGridComboBoxColumn.ElementStyle> <DataGridComboBoxColumn.EditingElementStyle>
    <Style TargetType="ComboBox">
        <Setter Property="ItemsSource" Value="{Binding Path=ModelCollection1}" />
    </Style> </DataGridComboBoxColumn.EditingElementStyle>

Here I have found answer http://cinch.codeplex.com/discussions/239522

For the DataGridComboBoxColumn you have to create a StaticRecource of the ItemsSource like:

<CollectionViewSource Source="{Binding Element=theView, Path=DataContext.ViewModelCollection1}" x:Key="ViewModelCollection1" />

and bind it to the DataGridComboBoxColumn with following:

ItemsSource="{Binding Source={StaticResource ViewModelCollection1}}"

Thats because the DataGridColumns are not a part of the visual tree.

And if you want to bind on a collection of a item of the DataGrid you have to set the ItemsSource over the two styles:

<DataGridComboBoxColumn.ElementStyle>
    <Style TargetType="ComboBox">
        <Setter Property="ItemsSource" Value="{Binding Path=ModelCollection1}" />
    </Style> </DataGridComboBoxColumn.ElementStyle> <DataGridComboBoxColumn.EditingElementStyle>
    <Style TargetType="ComboBox">
        <Setter Property="ItemsSource" Value="{Binding Path=ModelCollection1}" />
    </Style> </DataGridComboBoxColumn.EditingElementStyle>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文