16

私は最近、今後のプロジェクトのために WPF を使用して MVVM パターンの調査を開始しました。Josh Smith の MSDN 記事から始めました。質問があります (たくさんありますが、まずは 1 つから始めましょう):

モデルのプロパティを公開する IndividualViewModel があります。ご想像のとおり、「個人を追加」と「個人を編集」の 2 つのビューが必要です。私が現在行っていることは、AddIndividualViewModel と EditIndividualViewModel の 2 つのサブクラスを作成して、それぞれ Add コマンドと Edit コマンドを公開することです。これらにバインドする 2 つの類似した名前のビューもあります。

現在、このメソッドは機能しており、これらのクラスはとにかくかなり小さいですが、両方のコマンドを公開するビュー モデルを 1 つだけ持つことができるかどうか疑問に思っています。この同じビュー モデルにバインドする 2 つのビューがまだあり、適切なコマンドをボタンとして公開します。これを行う方法がよくわかりません。メインウィンドウのリソースには、次のようなものがあります。

        <DataTemplate DataType="{x:Type ViewModels:AddIndividualViewModel}">
            <Views:AddIndividualView />
        </DataTemplate>

このバインド方法では、1 対 1 のバインドのみを行うことができます。つまり、特定のビュー モデルに対して常に同じビューが表示されます。ビュー モデルのプロパティ (IndividualViewModel.Mode など) に応じてビューを自動的に切り替える方法はありますか。検討すべき別のアプローチはありますか?

メイン ウィンドウにはビュー モデルのコレクションがあり、それぞれがタブに表示されることに注意してください。

ありがとうございました!

4

4 に答える 4

6

したがって、プロパティ値に基づいて 2 つの異なるビューが必要です。考慮すべきことの 1 つは、プレゼンテーション コードをリファクタリングすることです。これにより、プロパティの値の代わりに実際のサブクラスを作成できます。DataTemplateその後、クラスごとに2 つの異なるものを使用できます。

<DataTemplate DataType="{x:Type ViewModels:AddIndividualViewModel}">
  <Views:AddIndividualView />
</DataTemplate>

<DataTemplate DataType="{x:Type ViewModels:EditIndividualViewModel}">
  <Views:EditIndividualView />
</DataTemplate>

それがやり過ぎだと思う場合は、トリガーを使用して、特定のビューをContentPresenter.

<DataTemplate x:Key="AddIndividualTemplate" DataType="{x:Type ViewModels:IndividualViewModel}">
  <Views:AddIndividualView />
</DataTemplate>

<DataTemplate x:Key="EditIndividualTemplate" DataType="{x:Type ViewModels:IndividualViewModel}">
  <Views:EditIndividualView />
</DataTemplate>

<DataTemplate DataType="{x:Type ViewModels:IndividualViewModel}">
  <ContentPresenter Content="{Binding}">
    <ContentPresenter.Style>
      <Style TargetType="ContentPresenter">
        <Setter Property="ContentTemplate" Value="{StaticResource AddIndividualTemplate}" />
        <Style.Triggers>
          <DataTrigger Binding="{Binding Mode}" Value="{x:Static ViewModels:IndividualMode.Edit}">
            <Setter Property="ContentTemplate" Value="{StaticResource EditIndividualTemplate}" />
          </DataTrigger>
        </Style.Triggers>
      </Style>
    </ContentPresenter.Style>
  </ContentPresenter>
</DataTemplate>
于 2015-03-11T13:08:10.550 に答える
4

私を正しい方向に向けてくれてありがとう!私もまだ WPF の初心者であり、バインディング メソッドを含むさまざまな可能性について学んでいます。とにかく、興味のある人は、この特定のケースで私がたどり着いた解決策を次に示します。

1 つのクラスで状態を管理しようとするのではなく、コマンドのみを公開する 2 つのサブクラス AddIndividualViewModel と EditIndividualViewModel にビュー モデルを分けておくことにしました。ただし、XAML を複製しないように、1 つのビューが必要でした。ビュー モデルに応じてアクション ボタンを切り替えるために、2 つの DataTemplates と DataTemplateSelector を使用することになりました。

        <DataTemplate x:Key="addTemplate">
            <Button Command="{Binding Path=AddCommand}">Add</Button>
        </DataTemplate>

        <DataTemplate x:Key="editTemplate">
            <Button Command="{Binding Path=UpdateCommand}">Update</Button>
        </DataTemplate>

        <TemplateSelectors:AddEditTemplateSelector
            AddTemplate="{StaticResource addTemplate}"
            EditTemplate="{StaticResource editTemplate}"
            x:Key="addEditTemplateSelector" />

フォームの下部にあるコンテンツ プレゼンター:

        <ContentPresenter Content="{Binding}"
                          ContentTemplateSelector="{StaticResource addEditTemplateSelector}" />

テンプレート セレクターのコードは次のとおりです。

class AddEditTemplateSelector : DataTemplateSelector
{
    public DataTemplate AddTemplate { get; set; }
    public DataTemplate EditTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        if (item is AddIndividualViewModel)
        {
            return AddTemplate;
        }
        else if (item is EditIndividualViewModel)
        {
            return EditTemplate;
        }

        return null;
    }
}

これは、最終的なものを実装する方法である場合とそうでない場合があります (要件が与えられた場合) が、この種のオプションが利用可能であることを確認するのは良いことです。

于 2010-01-03T13:29:56.290 に答える
0

このタスクでは、DataTemplateSelector はまったく必要ありません。

  1. EditIndividualVM と AddINdividualVM の両方を IndividualVM から派生させます。
  2. Edit- および AddCommands は、IndividualVM のセッター プロパティにルーティングします。
  3. 押されたボタンに応じて、セッター VM = new AddIndividualVM または VM = new EditIndividualVM になります。
  4. xaml では、次のように contentgrid を VM プロパティにバインドします。

于 2010-03-21T17:52:09.463 に答える
0

それを達成できない理由はありません。これを行う 1 つの方法は、ビュー モデルに、追加モードか編集モードかを示すフラグを提供し、単純なバインド、トリガー、またはテンプレート セレクターを使用して、そのフラグに基づいてビューをスタイル設定することです。

参考までに、彼のフレームワークの一部であるSacha Barber のDataWrapperクラスCinch(あなたのケースには直接適用できませんが、これは良い出発点です) を見ることができます。 (レコード表示モード)、読み取り/書き込み (レコード編集モード)。同様のアプローチを適用して、追加と編集を区別できます。

Value基本的に、ビュー モデルに単純なプロパティを含める代わりに、プロパティとプロパティを含むデータ ラッパー クラスをインスタンス化しIsAddingます。ビューでは、バインディング、トリガー、またはテンプレート セレクターを使用して、そのプロパティに基づいてテンプレートを変更できます。

于 2010-01-01T14:23:52.073 に答える