WPF,MVVM从字典中填充级联组合框
Posted
技术标签:
【中文标题】WPF,MVVM从字典中填充级联组合框【英文标题】:WPF, MVVM Populating Cascading ComboBoxes from a dictionary 【发布时间】:2022-01-06 08:14:26 【问题描述】:所以,我有一个包含 2 个组合框的 UserControl,我想从字典中填充它们。所以 ComboBoxA 被字典键填充,而 ComboBoxB 被字典[ComboBoxA selected item] 填充。如何使用 MVVM 实现这一目标? Category 基本上是 int,Parameter 是一个字符串。 到目前为止我的代码:模型
public class CategoryUserControlModel
public Dictionary<Category, List<Parameter>> parametersOfCategories get; set;
public Category chosenCategory get; set;
public Parameter chosenParameter get; set;
视图模型
public class CategoryUserControlViewModel
public CategoryUserControlViewModel(CategoryUserControlModel controlModel)
Model = controlModel;
public CategoryUserControlModel Model get; set;
public Category ChosenCategory
get => Model.chosenCategory;
set
Model.chosenCategory = value;
public Parameter ChosenParameter
get => Model.chosenParameter;
set => Model.chosenParameter = value;
XAML
<Grid>
<ComboBox x:Name="Categories" HorizontalAlignment="Left" Margin="0,14,0,0" VerticalAlignment="Top" Width="120" ItemsSource="Binding Model.parametersOfCategories.Keys"/>
<TextBlock x:Name="Text" HorizontalAlignment="Left" Height="15" Margin="0,-2,0,0" TextWrapping="Wrap" Text="Категория" VerticalAlignment="Top" Width="60"/>
<ComboBox x:Name="Parameter" HorizontalAlignment="Left" Margin="125,14,0,0" VerticalAlignment="Top" Width="120" ItemsSource="Binding Model.parametersOfCategories.Values/>
<TextBlock x:Name="ParameterText" HorizontalAlignment="Left" Height="15" Margin="125,-2,0,0" TextWrapping="Wrap" Text="Параметр" VerticalAlignment="Top" Width="60"/>
</Grid>
</UserControl>
【问题讨论】:
【参考方案1】:您为模型和视图模型使用了不恰当的名称,它们不应该与视图相关联,并且您的模型不应该包含名称给人以模型需要用户交互的印象的成员。考虑一个类似于这个的改进版本:
public class CategoryWithParameterModel
public Dictionary<Category, List<Parameter>> ParametersOfCategories get; set;
public Category Category get; set;
public Parameter Parameter get; set;
您的 viewmodel 必须实现 INotifyPropertyChanged
接口,以便通知 UI 它需要刷新绑定,这对于模型来说不是必需的,因为您将它包装在 viewmodel 中。也就是说,您的视图模型定义将变为:
public class CategoryWithParameterViewModel : INotifyPropertyChanged
...
接下来,既然你想绑定到字典中的一个列表,那么你的视图模型必须公开一个指向该列表的属性,我们称之为AvailableParameters
,所以它应该这样定义:
public List<Parameter> AvailableParameters
get
if (Model.ParametersOfCategories.ContainsKey(ChosenCategory))
return Model.ParametersOfCategories[ChosenCategory];
else
return null;
这是需要绑定到名为“参数”的第二个组合框的ItemsSource
的属性:)
但是,ChosenCategory
属性根本没有绑定,因此您需要将其绑定到第一个组合框的选定项,以便能够检测允许 viemodel 查找参数列表的用户选择,同样适用于 @ 987654328@,所以这里是更新的xaml代码:
<Grid>
<ComboBox x:Name="Categories" HorizontalAlignment="Left" Margin="0,14,0,0" VerticalAlignment="Top" Width="120" ItemsSource="Binding Model.ParametersOfCategories.Keys" SelectedItem="Binding ChosenCategory"/>
<TextBlock x:Name="Text" HorizontalAlignment="Left" Height="15" Margin="0,-2,0,0" TextWrapping="Wrap" Text="Категория" VerticalAlignment="Top" Width="60"/>
<ComboBox x:Name="Parameter" HorizontalAlignment="Left" Margin="125,14,0,0" VerticalAlignment="Top" Width="120" ItemsSource="Binding AvailableParameters" SelectedItem="Binding ChosenParameter"/>
<TextBlock x:Name="ParameterText" HorizontalAlignment="Left" Height="15" Margin="125,-2,0,0" TextWrapping="Wrap" Text="Параметр" VerticalAlignment="Top" Width="60"/>
</Grid>
最后,您必须在 ChosenCategory
发生更改时通知 UI,因此您需要为 AvailableParameters
引发 PropertyChanged
事件。实现它将使视图模型变成这样:
public class CategoryWithParameterViewModel : INotifyPropertyChanged
public CategoryWithParameterViewModel(CategoryWithParameterModel model)
Model = model;
// This should be read-only
public CategoryWithParameterModel Model get; /*set;*/
public Category ChosenCategory
get => Model.Category;
set
Model.Category = value;
OnPropertyChanged(nameof(AvailableParameters));
public Parameter ChosenParameter
get => Model.Parameter;
set => Model.Parameter = value;
public List<Parameter> AvailableParameters
get
if (Model.ParametersOfCategories.ContainsKey(ChosenCategory))
return Model.ParametersOfCategories[ChosenCategory];
else
return null;
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
【讨论】:
以上是关于WPF,MVVM从字典中填充级联组合框的主要内容,如果未能解决你的问题,请参考以下文章