MVVM - 具有多态性的集合

Gio*_*der 4 c# wpf .net-4.0 mvvm

我试图在ListBox中公开两个派生类型:OutFlight和InFlight都派生自Flight,它是一个抽象类型.

MVVM说我必须为ListBox的绑定模型设置ViewModel.对于一种类型的曝光来说,这不是什么大问题,但我的列表框包含两种派生类型,我正在寻找最好的MVVM方法.这是否意味着我必须为每个派生类型设置继承的ViewModel?我已经读过某处ViewModel继承不被推荐......我确信这是一个非常常见的情况

And*_*dre 6

有几种方法.一种方法是为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; }
}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用一些基本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>
Run Code Online (Sandbox Code Playgroud)