我试图在 ListBox 中公开两种派生类型:OutFlight 和 InFlight 都派生自作为抽象类型的 Flight。
MVVM 说我必须为 ListBox 的绑定模型设置一个 ViewModel。公开一种类型并不是什么大问题,但我的列表框包含两种派生类型,我正在寻找最好的 MVVM 方法。这是否意味着我必须为每个派生类型设置继承的 ViewModel?我在某处读过 ViewModel 继承根本不推荐......我敢肯定这是一个非常常见的情况
有几种方法。一种方法是为您的 Flight 类编写一个 ViewModel,并用这些“FlightViewModel”对象填充一个集合。该 ViewModel 可以包含从“Flight”继承的所有对象。如果您的“InFlight”和“OutFlight”类不那么复杂,我会将它们包装在一个 ViewModel 中(这里是“FlightViewModel”)。
public class FlightViewModel : INotifyPropertyChanged
{
public Flight Flight { get; set; }
public int PropertyYouNeedForInFlight { get; set; }
public string PropertyYouNeedForOutFlight { get; set; }
}
另一种方法是使用一些基本 ViewModel 类型的集合作为 ListBox ItemsSource。该集合包含一些“InFlightViewModel”类型的 ViewModel 和其他一些“OutFlightViewModel”类型的 ViewModel。对于您的 ListBox 项目,您可以编写一个 ItemTemplateSelector,为项目类型选择正确的 ItemTemplate。
public class MainWindowViewModel
{
public ObservableCollection<ViewModelBase> Flights { get; set; }
public MainWindowViewModel()
{
Flights = new ObservableCollection<ViewModelBase>();
Flights.Add(new InFlightViewModel());
Flights.Add(new OutFlightViewModel());
}
}
public class FlightTemplateSelector : DataTemplateSelector
{
public DataTemplate InFlightTemplate { get; set; }
public DataTemplate OutFlightTemplate { get; set; }
public override DataTemplate SelectTemplate(object item,
DependencyObject container)
{
if(item.GetType() == typeof(InFlight))
return InFlightTemplate;
if(item.GetType() == typeof(OutFlight))
return OutFlightTemplate
//Throw exception or choose some random layout
throw new Exception();
}
}
<local:FlightTemplateSelector
x:Key="FlightTemplateSelector">
<local:FlightTemplateSelector.InFlightTemplate>
<!-- Define your layout here -->
</local:FlightTemplateSelector.InFlightTemplate>
<!-- Define your layout here -->
<local:FlightTemplateSelector.OutFlightTemplate>
</local:FlightTemplateSelector.OutFlightTemplate>
</local:FlightTemplateSelector>
您可以创建一个封装 OutFlight 和 InFlight 实体的通用视图模型 FlightViewModel。因此 FlightViewModel 具有所有通用属性,并且基于 OutFlight 和 InFlight 实体构建(例如通过在构造函数中传递它们)。它可能有一个额外的属性,指示它是飞行还是飞行(作为枚举或其他东西)。
这样做会使 FlightViewModel 基本上成为具体类型 OutFlight 和 InFlight 的抽象。FlightViewModel 也将仅包含您在视图中实际需要的属性,并且格式正确,以便视图可以轻松使用它。
然后,您的视图的视图模型将具有 FlightViewModel 对象的集合。
public class FlightViewModel
{
private Flight _flight;
public FlightViewModel(OutFlight outFlight)
{
FlightNumber = outFlight.FlightNumber;
FlightType = FlightType.OutFlight;
_flight = outFlight;
}
public FlightViewModel(InFlight inFlight)
{
FlightNumber = inFlight.FlightNumber;
FlightType = FlightType.InFlight;
_flight = inFlight;
}
public int FlightNumber
{
get { return _flight.FlightNumber; }
set { _flight.FlightNumber = value; }
}
public FlightType FlightType { get; set; }
... other properties
}
这当然只是一个例子,但你明白了。