3

私のアプリケーションは、複数のデザイナー ウィンドウを持つことができます。各ウィンドウは、RelayCommands を使用して動的に通信する複数のユーザー コントロールで構成されます。指揮インフラストラクチャのバックボーンとして、次のクラスを作成しました。

public static class Commands
{
    public static readonly RoutedCommand EntityEditRequest = new RoutedCommand();
    public static  RelayCommand EntityEditorChangeRequest;
    public static RelayCommand XMLUpdateRequest;
    public static RelayCommand SaveRequest;   
}

ユーザーコントロールの各ビューモデルは、コンストラクターで次のようなことを行います

 public XMLEditorViewModel()
 {
        Commands.Commands.SaveRequest = new RelayCommand(Save_Executed);
        Commands.Commands.XMLUpdateRequest = new RelayCommand(UpdateXML); 
 }

ただし、アプリケーションが複数のウィンドウを持つことができるという点を完全に見逃していました。各ウィンドウが開かれると、その特定のウィンドウに対して静的コマンドが設定されます。

例:

ウィンドウ A が開かれます。usercontrols のコンストラクターが RelayCommands を設定し、すべて問題ありません。

ウィンドウ B が開きました。ユーザー コントロールのコンストラクターが RelayCommands を設定します。ウィンドウ A のコマンド バインドが失われました。

そのため、タブをウィンドウ A (ウィンドウはタブ付き) に変更すると、コマンドが機能しません。

タブを変更すると、アクティブなウィンドウが常にコマンドを設定するように、いくつかのアイデアが必要です。コマンドを tab_selection_changed イベントに入れようとすることはできますが、どういうわけか私には見栄えが悪いです。これを行う適切な方法はありますか?どんな助けでも大歓迎です。

編集:

この質問は、読者の間で少し混乱を招きました。コマンドに対して複数のサブスクライバーを作成しようとしているわけではありません。どの時点でも、アクティブなウィンドウは 1 つだけです。このウィンドウはいくつかのユーザー コントロールで構成されており、その一部はコマンドを使用して動的にロードされます。ただし、各コマンドは単一のビュー モデル クラスによって処理されるため、複数のサブスクライバーはありません。私の問題は、アプリケーションが複数のウィンドウをタブにロードできることです。特定の時点でアクティブなウィンドウは1つだけですが、ユーザーは別のタブで別のウィンドウをアクティブにすることができます。ビュー モデル コンストラクターが静的 RelayCommands を割り当てると、新しいウィンドウが読み込まれるたびに静的コマンドが新しいバインディングに設定されます。

ウィンドウ 開いたウィンドウ ビュー モデル コンストラクターは、静的コマンド バインドをそのオブジェクト コマンド ハンドラーに設定します。ウィンドウ A がアクティブです。指揮はいいです。

Window B loaded-window B ビュー モデル コンストラクターは、静的コマンド バインドをそのオブジェクト コマンド ハンドラーに設定します。ウィンドウ B がアクティブです。指揮はいいです。

ここで、[ウィンドウ A] タブを選択して、ウィンドウ A をアクティブに設定します。指揮は効かない。もちろん、コマンドはウィンドウ B コマンド ハンドラーにバインドされているため、問題はありません。

理論的には静的コマンドは、任意の時点でアクティブなウィンドウが 1 つしかないため、シナリオを処理できます。しかし、どのように??

4

4 に答える 4

2

グローバル コマンドは、CompositeCommandまたは同様のアプローチである必要があります (CompositeCommandは Prism からのものです)。これにより、複数の子がコマンドに登録できるようになります。

  public static CompositeCommand SaveCommand = new CompositeCommand();

コマンドは、ViewModels または該当する場合にアクセスできます...

  SaveCommand = new DelegateCommand<object>(Save, CanExecuteSave);
  GlobalCommands.SaveCommand.RegisterCommand(SaveCommand);

IActiveAware次に、インターフェイスを活用して、どれWindowがアクティブであるかを定義しWindow、それに応じてコマンドを実行できます。

グローバルに利用可能なコマンドの作成に関する MSDN の投稿もあります。メモリ リークを避けるために、コマンドを登録解除することを忘れないでください。

于 2011-03-25T22:36:09.923 に答える
1

ビュー固有ではないコマンドは、静的クラスで定義できます。

ビュー固有のコマンドは、view-model で定義し、DataContext としてビューに渡して、異なるビュー モデルで異なるビューの個別の実装を有効にするか、少なくともビューを識別するために使用できる CommandParameter をビューに渡す必要があります (例:ビューへの参照) またはそれらの DataContext。

コマンドが静的である場合は、おそらくビュー モデルで使用されるシングルトンで一度だけ登録します。

于 2011-03-25T23:03:22.290 に答える
1

それを静的クラスに入れることにした理由は何ですか?

class XMLEditorViewModel
{
    public ICommand SaveRequest { get; private set; }

    public XMLEditorViewModel()
    {
        SaveRequest = new RelayCommand(Save_Executed)?
    }
}
于 2011-03-25T22:12:01.283 に答える
0

グローバルに使用可能なコマンドを作成し、DelegateCommand または CompositeCommand のインスタンスを作成して、静的クラスを通じて公開します。

public static class GlobalCommands { public static CompositeCommand MyCompositeCommand = new CompositeCommand(); モジュールで、子コマンドをグローバルに使用可能なコマンドに関連付けます。

GlobalCommands.MyCompositeCommand.RegisterCommand(command1); GlobalCommands.MyCompositeCommand.RegisterCommand(command2); コードのテスト容易性を高めるために、プロキシ クラスを使用してグローバルに使用可能なコマンドにアクセスし、テストでそのプロキシ クラスをモックできます。

次のコード例は、ボタンを WPF のコマンドにバインドする方法を示しています。

複合コマンドを実行

于 2011-04-27T11:15:00.410 に答える