C# 基于DataGrid项更改DataGridComboxColumn项源
在我的应用程序中,我使用C#、WPF,并且遵循MVVM模式 我正在努力实现以下目标: 我有一个C# 基于DataGrid项更改DataGridComboxColumn项源,c#,wpf,mvvm,combobox,C#,Wpf,Mvvm,Combobox,在我的应用程序中,我使用C#、WPF,并且遵循MVVM模式 我正在努力实现以下目标: 我有一个DataGrid,它ItemSource在我的ViewModel中的Collection上绑定MyObject有两个enum属性,即TypeA和TypeB(TypeA是与TypeB不同的枚举类型) 数据网格的每一行都有一个组合框,用户可以通过选择一个可用值来更改TypeB值。用户无法更改类型A。然而,TypeB的可用值基于TypeA的值 <DataGridTemplateColumn Header
DataGrid
,它ItemSource
在我的ViewModel中的Collection
上绑定MyObject
有两个enum
属性,即TypeA和TypeB(TypeA是与TypeB不同的枚举类型)
数据网格的每一行都有一个组合框
,用户可以通过选择一个可用值来更改TypeB值。用户无法更改类型A。然而,TypeB的可用值基于TypeA的值
<DataGridTemplateColumn Header="Type B">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox SelectedItem="{Binding TypeB, UpdateSourceTrigger=PropertyChanged}">
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Converter={StaticResource DescriptionConverter}}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
和视图模型
public ICollectionView AvailableTypeB
{
get
{
ObservableCollection<TypeB> availableTypeB = new ObservableCollection<TypeB>((TypeB[])Enum.GetValues(typeof(TypeB)));
// Here based on the TypeA property of the SelectedRow in the grid
// I am populating the availableTypeB collection with the needed values based on the aforementioned rules
return CollectionViewSource.GetDefaultView(availableTypeB);
}
}
公共ICollectionView可用PEB
{
得到
{
ObservableCollection availableTypeB=新的ObservableCollection((TypeB[])Enum.GetValues(typeof(TypeB));
//此处基于网格中SelectedRow的TypeA属性
//我正在根据上述规则使用所需的值填充availableTypeB集合
返回CollectionViewSource.GetDefaultView(availableTypeB);
}
}
*SelectedRow
是一个绑定到数据网格的SelectedItem的项
我还尝试过,而不是每次创建集合并返回默认视图,而是为TypeB枚举项创建一次CollectionView,每次都基于SelectedRow
应用一个新的过滤器
这种方法的问题是,当AvailableTypeB发生变化时,ComboBox的SelectedItem为null,SelectedItem不再是它的一部分。我试图改变绑定模式
和IsSynchronizedWithCurrentItem
,但没有成功
我尝试的第二种方法是在ComboBox.Loaded事件上填充ComboBox.ItemsSource。这可以通过几种方式实现,我尝试的是
-。具有已加载的事件,并且在代码隐藏中执行ComboBox.ItemsSource=
-。使用交互性引用以使用命令而不是加载的事件
它们都在某种程度上“打破”了MVVM模式。使用交互性程序集时,我必须将组合框
控件传递给模型,以便访问其数据源,这直接违反了MVVM
我知道还有第三种方法,即使用我尚未尝试过的附加行为
将可用TypeB值的集合作为myMyObject
类中的唯一get属性。这是一个更干净的解决方案,但是它使我的MyObject
类不那么通用。在我的程序的某些部分中,用户可以更改上述规则不适用的TypeB
值,这就是我希望避免这种方法的原因
注意1:由于这是一篇很长的文章,我试图将代码样本保持在最小。如果您认为缺少某些详细信息,请询问他们,我将进行编辑/更新。
注2:我知道问题的某些部分可能是“基于意见的”,也许codeReview是一个更好的地方。我建议您按照选项3中的方法,将其命名为TypeBListFiltered
或其他(基于SelectedTypeA
属性的过滤器),并以TypeBList
的形式公开一个单独的完整的TypeB列表。消费者使用合适的列表。这并不是“不那么通用”。但是您也可以编写一个ValueConverter,它接受一个TypeA参数,并返回一个经过筛选的TypeB值集合。你知道,你的选择2是个坏主意。A.fil@EdPlunkett说实话,我喜欢转换器(我也这么认为,但我没有提到)。然而,我的意见是,转换器不打算以这种方式使用。顾名思义,它们是在转换值,而不是过滤值。从另一个角度看,你可以说过滤是一种转换。没错,你通常认为转换器转换标量值,而不是将未过滤的集合转换为过滤的集合。但对于一个小的不断收集,我并不认为这是滥用机制。它不会产生任何难看的惊喜,也不会在运行时淹没您。如果我看到ItemsSource=“{Binding SelectedTypeA,Converter={StaticResource TypeBFilterConverter}}”
,我就不必浪费时间猜测我在看什么了。
<ComboBox ItemsSource="{Binding TypeBAvailable}"
public ICollectionView AvailableTypeB
{
get
{
ObservableCollection<TypeB> availableTypeB = new ObservableCollection<TypeB>((TypeB[])Enum.GetValues(typeof(TypeB)));
// Here based on the TypeA property of the SelectedRow in the grid
// I am populating the availableTypeB collection with the needed values based on the aforementioned rules
return CollectionViewSource.GetDefaultView(availableTypeB);
}
}