4

我试图在 ListBox 中公开两种派生类型:OutFlight 和 InFlight 都派生自作为抽象类型的 Flight。

MVVM 说我必须为 ListBox 的绑定模型设置一个 ViewModel。公开一种类型并不是什么大问题,但我的列表框包含两种派生类型,我正在寻找最好的 MVVM 方法。这是否意味着我必须为每个派生类型设置继承的 ViewModel?我在某处读过 ViewModel 继承根本不推荐......我敢肯定这是一个非常常见的情况

4

2 回答 2

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; }
}

另一种方法是使用一些基本 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>
于 2013-04-10T10:42:55.740 回答
1

您可以创建一个封装 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
}

这当然只是一个例子,但你明白了。

于 2013-04-10T11:05:44.747 回答