0

コンベンションの難問:

簡単にするために、FruitViewという名前のビューがあり、「Choose afruit:」というラベルが付いていて、リストボックスにリンゴ、オレンジ、洋ナシなどの選択肢があるとします。

各アイテムはクラスのインスタンスです(Apple.cs、Orange.cs、Pear.csなど)。

ViewModelは、バインドされたプロパティを使用して、選択したフルーツを追跡します。

public Fruit CurrentFruit { get; set; }

「フルーツ」自体は、アップル、オレンジ、ペアなどのそれぞれが由来するインターフェースです。

ここで、別のステップとして、Apple、Orange、Pearなどのそれぞれ。Apple.csは、メソッドとイベントを持つAppleManager、OrangeManager、PearManagerなどと呼ばれる静的クラスに依存しています。これらのマネージャーは大きく異なり、共通のベースやインターフェースから派生したものではありません。

たとえば、AppleManagerには次のものがあります。

public delegate void ColorChangedEventHandler(string color);

public static event ColorChangedEventHandler ColorChanged;

private void RaiseColorChanged(string color)
{
    if (ColorChanged != null)
    {
        ColorChanged(color);
    }
}

ビューで「アップル」が選択されている場合、ビューの残りのボタン、画像などは、AppleManagerで発生したイベントに反応する必要があります。「オレンジ」が選択されている場合、ビューはOrangeManagerのイベントに反応する必要があります。

それで、問題は、ViewModelのCurrentFruitのマネージャーにViewの反応メソッドを接続するための適切な経路は何ですか?

つまり、行くことが可能です:

private void FruitListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    // pseudocode: if apple selected, AppleManager.ColorChanged += new ColorChangedEventHandler(CurrentFruit_ColorChanged);
}

private void CurrentFruit_ColorChanged(string color)
{
    FruitColorTextBox.Text = color;
}

これが受け入れられない理由は、それがデザインパターンを壊し、あらゆる種類の果物を処理する必要があることを意味するためです。

実際には、果物のオプションの代わりに、私は多くの医療機器を持っており、余分なロジックを追加するのではなく、インターフェイスとしても使用したいと考えています。

私の現在の解決策は、次のように、インターフェイスVCONFにイベントを追加することでした。

public interface VCONF
{
    public static event CallIncomingEventHandler CallIncoming;
    public static event EventArgs CallStarted;
    public static event EventArgs CallEnded;
}

現在、VCONF1、VCONF2、VCONF3などはすべてVCONFから派生しており、これらのイベントを発生させるメソッドを使用してこれらのイベントを実装しています。

これは、各VCONF1などに同じイベント行を記述する必要があることを意味しますが、これは、複数のクラスがINotifyPropertyChangedを継承するのと同じです。そのため、このように設定しました)。また、同じイベントとraiseメソッドをVCONF1Managerで作成することも意味します。つまり、ビューがそれに反応するまで、raiseイベントのチェーン、レイヤー上のraiseイベント、レイヤー上のraiseイベントなどです。VCONF1Manager.CallIncoming->VCONF1.CallIncoming->ビューが反応します

VCONF1はVCONF1Managerのイベントにサブスクライブし、VCONF2はVCONF2Managerのイベントにサブスクライブします。

他のVCONF?マネージャーさえいないかもしれません。これらのイベントをいつ発生させるかを独自の方法で判断するだけです。

ビューは、選択されたときに現在のVCONFのイベントをサブスクライブします。

private void VCONF_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    (this.DataContext as VCONFViewModel).CurrentVCONF = (sender as ListBox).SelectedValue as VCONF;

    (((sender as ListBox).SelectedValue as VCONF).Device as VCONF).CallIncoming += new CallIncomingEventHandler(CurrentVCONF_CallIncoming);
    // same for other events
    ...
}

それで、私がここで本当に求めているのは、レイヤー/抽象化を介してイベントをチェーンするための、またはあなたの好ましい/従来の方法は何ですか?

私がやっていることはうまくいきますが、イベントを2倍にして、イベントを続けて連鎖させることが最善の方法ではないように感じずにはいられません。

前もって感謝します。

4

2 に答える 2

1

ビューはビューモデルのプロパティにバインドする必要があります。ビューモデルにビューイベントハンドラーを含めることはできません。CurrentFruit_ColorChangedしたがって、イベントハンドラーの代わりに、ビューはColorそのプロパティにバインドする必要があります。つまりDataContext、基本的にはfruit.Color。次に、変更の原因となったイベントではなく、プロパティの変更に基づいてビューモデルで適切に反応します。

ビューが果物の種類ごとに異なって見える必要がある場合は、データテンプレートを利用し、現在の果物が変更されたときにビューが自動的に構成されるようにする必要があります。すなわち:

<Window.Resources>
    <DataTemplate DataType="{x:Type Apple}">
        <!-- ... view for Apples ... -->
    </DataTemplate>
    <DataTemplate DataType="{x:Type Orange}">
        <!-- ... view for Oranges ... -->
    </DataTemplate>
    <DataTemplate DataeType="{x:Type Pear}">
        <!-- ... view for Pears ... -->
    </DataTemplate>
</Window.Resources>
<ContentControl Content="{Binding Path=CurrentFruit}"/>

上記の例のフルーツ固有のビューは、DataTypeのプロパティに接続します。ビューモデルがビューイベントをサブスクライブしようとするのではなく、ビューがビューモデルプロパティに接続しているときに、マネージャーの概念がなくなる可能性があります(すべきです)。

于 2013-03-06T20:12:46.400 に答える
0

コメントで述べたように、Microsoftの.NET標準規則に従って、イベントパスウェイを作り直しました。

私はもうこの経路にViewModelを使用していません。ViewModelは、デバイスのコレクション(またはフルーツなど)のように、ビューが直接使用して表示するオブジェクトを保持するためだけのものです。

ビューはインターフェイスに基づいて現在のデバイスと通信します。そのインターフェイスには、デバイスがビューに対して発生させるイベントがあり、標準のEventHandlerがあり、データEventArgsはありません。

各デバイスはこれらのイベントを実装し、内部ロジックがそうすることを決定したときにそれらを発生させます(デバイスマネージャークラスによって異なります)。

また、以前にイベントを介して渡そうとしていたデータを含むプロパティもインターフェースおよび実装されています。

ビューは、選択されるとすぐに現在のデバイスのイベントに接続し、それらのイベントが発生すると、ビューは「sender.IncomingCallerID」または「sender.CallStatus」などのプロパティを介してこれらの値にアクセスします。

したがって、基本的には、MicrosoftがListBoxでSelectionChangedを設定した後、送信者からSelectedValueプロパティにアクセスします。

于 2013-03-07T18:44:50.890 に答える