4

ListBox で 2 つの派生型を公開しようとしています: OutFlight と InFlight は両方とも、抽象型である Flight から派生しています。

MVVM は、ListBox のバインドされたモデルに ViewModel を設定する必要があると言っています。1 つの型を公開することは大したことではありませんが、私のリストボックスには 2 つの派生型が含まれており、最適な MVVM アプローチを探しています。派生型ごとに継承された ViewModel を設定する必要があるということですか? 私はどこかで ViewModel の継承はまったく推奨されていないことを読んだことがあります...非常に一般的なケースだと確信しています

4

2 に答える 2

6

いくつかの方法があります。1 つの方法は、Flight クラスの ViewModel を作成し、それらの "FlightViewModel" オブジェクトでコレクションを埋めることです。その ViewModel には、「Flight」から継承するすべてのオブジェクトを含めることができます。「InFlight」および「OutFlight」クラスがそれほど複雑でない場合は、それらを 1 つの ViewModel (ここでは「FlightViewModel」) にラップします。

public class FlightViewModel : INotifyPropertyChanged
{
    public Flight Flight { get; set; }

    public int PropertyYouNeedForInFlight { get; set; }
    public string PropertyYouNeedForOutFlight { get; set; }
}

もう 1 つの方法は、いくつかの基本 ViewModel タイプのコレクションを ListBox ItemsSource として使用することです。このコレクションには、「InFlightViewModel」タイプの ViewModel と「OutFlightViewModel」タイプのその他の ViewModel が含まれています。ListBox アイテムの場合、アイテムのタイプに適した ItemTemplate を選択する ItemTemplateSelector を作成できます。

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 に答える