我有2个listBox,如果你单击顶部的一个项目,那么底部的一个过滤到一些结果。 我正在尝试学习WPF和MVVM,我想知道这是否是正确的方法。这是最好的方式吗?
这是我做的:
class VisitInfoViewModel : ViewModelBase
{
List<ServiceType> serviceTypes;
List<ServiceType> allServiceTypes;
public VisitInfoViewModel()
{
ServiceCategories = ServiceCategory.Categories;
allServiceTypes = ServiceType.ServiceTypes;
}
public List<ServiceCategory> ServiceCategories { get; set; }
public List<ServiceType> ServiceTypes
{
get
{
return serviceTypes;
}
}
public ServiceCategory SelectedServiceCategory
{
get { return null; }
set
{
serviceTypes = allServiceTypes.FindAll(st => st.ServiceCategoryGuid.Equals(value.Guid));
OnPropertyChanged("ServiceTypes");
}
}
}
和MainWindow.xaml代码段
<ListBox ItemsSource="{Binding Path=VisitInfo.ServiceCategories}"
SelectedItem="{Binding Path=VisitInfo.SelectedServiceCategory}"
ItemTemplate="{StaticResource listBoxTemplate}"
Height="112"
HorizontalAlignment="Left"
Margin="6,30,0,0"
Name="lbxServiceCategory"
VerticalAlignment="Top"
Width="366" />
<ListBox ItemsSource="{Binding Path=VisitInfo.ServiceTypes}"
ItemTemplate="{StaticResource listBoxTemplate}"
HorizontalAlignment="Left"
Margin="6,0,0,19"
Name="lbxServiceType"
Width="366"
Height="121"
VerticalAlignment="Bottom" />
另外,为什么我不应该在listBox上为selectedItemChanged添加一个EventHandler? 使用事件处理程序似乎更简单,更清晰。 我认为这是因为如果我这样做它将不再是MVVM ......这是正确的吗? 你会做什么,最佳做法是什么?
答案 0 :(得分:0)
你正在做的事情大部分时间都很好 - 尽管我会亲自将SelectedServiceCategory
变成一个“真正的”属性(带有保存的值)。
与MVVM的不同之处在于,您在处理代码时,是在处理数据。如果您使“当前类别”更改类型,那么您将完全使用数据,而不必担心UI。您可以通过任何机制更改类别,UI将始终保持最新。
我个人建议写这个更像:
class VisitInfoViewModel : ViewModelBase
{
List<ServiceType> allServiceTypes;
public VisitInfoViewModel()
{
ServiceCategories = ServiceCategory.Categories;
allServiceTypes = ServiceType.ServiceTypes;
}
// This can use a private setter...
public IEnumerable<ServiceCategory> ServiceCategories { get; private set; }
private ServiceCategory currentCategory;
public ServiceCategory CurrentServiceCategory
{
get { return this.currentCategory; }
set
{
if (this.currentCategory != value)
{
this.currentCategory = value;
ServiceTypesInCurrentCategory = allServiceTypes.Where(st => st.ServiceCategoryGuid.Equals(this.currentCategory.Guid));
OnPropertyChagned("CurrentServiceCategory");
OnPropertyChanged("ServiceTypes");
}
}
}
public IEnumerable<ServiceType> ServiceTypesInCurrentCategory { get; private set; }
}
这样可以完全自由地在代码中或通过Xaml更改CurrentServiceCategory
,而无需任何事件处理程序。它还使您的ViewModel完全与数据相关 - 您不知道或不关心用于显示此内容的内容 - 只要您在View中设置了某些来设置CurrentServiceCategory
,所有内容保持同步正确。
另外,为什么我不应该在listBox上为selectedItemChanged添加一个EventHandler?使用事件处理程序似乎更简单,更清晰。我认为这是因为如果我这样做它将不再是MVVM ......这是正确的吗?
你可以这样做,但此时通常违反了MVVM。主要问题是您要将实现与该事件处理程序相结合 - 通过这样做,您基本上“锁定”了View中针对此特定View实现的代码的行为。通过在MVVM方面保持“纯粹”,你可以自由地改变View(即:你可能希望有一天切换到ServiceCategories的组合框),而根本不会触及你的ViewModel代码......