MVVMモデルは初めてです。ボタンの数を使ったユーザーコントロールがあります。RoutedEventを介してビューモデルクラスのこれらのボタンのクリックイベントを処理しています。ボタンのクリックイベントで別のユーザーコントロールを呼び出す/開く必要があります。これを達成する方法は?
前もって感謝します...
MVVMモデルは初めてです。ボタンの数を使ったユーザーコントロールがあります。RoutedEventを介してビューモデルクラスのこれらのボタンのクリックイベントを処理しています。ボタンのクリックイベントで別のユーザーコントロールを呼び出す/開く必要があります。これを達成する方法は?
前もって感謝します...
あなたが説明することは、MVVMに慣れていないほとんどの人が苦労する問題の1つです-ナビゲーション。私は一般的に、ビューモデルのいずれかがそれ自体のビュー (ビューモデルはかなりビューにとらわれないはずです) や他のビューについての知識を持たないようにしています。
これを解決する 1 つの方法は、すべてのナビゲーションを処理する中心的なコンポーネントをアプリケーションに配置することです。これを NavigationController と呼びましょう。このコンポーネントは、ナビゲーション リクエストを処理し、ビュー (およびオプションで関連付けられたビューモデル) の作成とそれらの初期化を担当します。また、さまざまなビューモデルとそれぞれのビューの間の相互依存性を実際に認識しているアプリケーション内の唯一のコンポーネントです。
理想的には、ViewModel と Controller 間の通信は Event Aggregator ( TinyMessengerなど) を介して実行されます。これにより、疎結合のナビゲーション (およびその他の機能) を簡単に実装できます。
最後の発言として、単純な UserControl ではなく、子ウィンドウでホストされている UserControl を意味するある種のダイアログを表示することを意味していたのではないかと思います。これも、私が概説したアプローチを使用して解決できます。
やりたいことを実行するには、コントロールとフォームを組み合わせて使用する必要があります。私の答えはSilverlight 4以降に適用されることに注意してください。まず、ボタン「COMMAND」をビュー モデル コマンドの実装にバインドします。次の例では、コントロールの DataContext はビュー モデルのインスタンスです。私の ViewModel は、キー (文字列) と ViewModelCommand クラスのセットのハッシュ テーブルを実装しています。実装の複雑さは無視してください。ポイントは、ボタンが「コマンド」にバインドされていることです
<Button Style="{StaticResource stTitleButton}" Height="Auto" Foreground="White"
Command="{Binding ViewModelCommandIoC.ViewModelCommands[FIND]}"
CommandParameter="{Binding ElementName=enHiddenControl}"
Visibility="{Binding CanSwitchCustomer,Converter={StaticResource VisibilityValueConverter},FallbackValue=Collapsed}"
>
上記の例では、コマンドは "FIND" でインデックス付けされたコマンドにバインドされています。コマンドに直接バインドするのと同じです。次に重要な部分は CommandParameter です。これは、新しいウィンドウに表示したいコントロールの隠しインスタンスです。この場合のコントロールの名前は「enHiddenControl」です。このコントロールは画面のどこにでも配置できますが、非表示になっていることを確認してください。これは、コマンドのメソッド シグネチャのパラメーターとして入ります。例えば:
/// <summary>
/// Finding an existing customer
/// </summary>
/// <param name="sender">The command parameter - control </param>
/// <param name="e"></param>
public void OnChangeCustomer(object sender)...
このセンダーが入ってきたときの目標は、タイプを取得し、アクティベーターを使用してそのクラスのインスタンスを作成することです。Activator はSystem.ReflectionまたはSystem.Reflection.Emitにあります。(私はこれを頭の上から入力しています。これは主に理論的なものですが、うまくいくはずです;)
Activator.CreateInstance(sender.GetType())
このクラスのインスタンスを作成したら、それを「ChildControl」の LayoutGrid に追加します。どのように?グリッドを作成し、「LayoutRoot」という名前を付けます。ChildControl を作成し、グリッドを子コントロールに追加してから、作成したばかりのインスタンスをグリッドに追加します。フォームを表示します。理論的には、特定のクラスについて知らなくても、コントロールを使用してフォームを動的に作成しただけです。ジェネリックのみ。フォームのサイジング....それは別の話です. 幅と高さの両方に Auto を使用します。結果として、コントロールのサイズは、理論的にはフォームのサイズを決定する必要があります。
最後に、メソッドは次のようになります。
public void OnChangeCustomer(object sender)
{
//the search screen
if (sender is UserControl)
{
UserControl uc = Activator.CreateInstance(sender.GetType()) as UserControl;
Grid grdLayoutRoot = new Grid();
grdLayoutRoot.Name = "LayoutRoot";
grdLayoutRoot.Children.Add(uc);
ChildWindow cw = new ChildWindow();
cw.Content = grdLayoutRoot;
cw.Show();
}
}
これはすべて理論上のものであり、テストされたことはありませんが、C# でこの種の性質のスタントを引っ張ってきた回数を考えると、うまくいくはずです。
表示プロパティを折りたたんで XAML にコントロールを配置し、イベント ハンドラーで表示を変更します。
<TextBlock HorizontalAlignment="Left" Visibility="Collapsed" Name="ErrorBlock" Text="Authentication Failed." VerticalAlignment="Top" Foreground="Red" FontWeight="Bold" />
C#から
ErrorBlock.Visibility = System.Windows.Visibility.Visible;
もう1つのオプションは、プログラムでコントロールを作成し、それらを親に追加することです。たとえば、グリッドは次のリンクを参照して、グリッドに長方形を追加するサンプルを取得します