2

現在、MVVM (Light) を使用して WPF でアプリケーションを構築しています。ただし、場合によっては、ユーザーがボタンをクリックしたときに新しいダイアログ (WPF も) を開く必要があります。しかし、これは厳しい戦いです。

これが私がやっている方法です:

    private void _ShowItemDialog(Item item)
    {
        var itemVM = new ItemViewModel();
        itemVM.CurrentItem = item ?? new Item();
        itemVM.Load();

        var itemView = new View.ItemView() { DataContext = itemVM };
        if (itemView.ShowDialog() == true)
        {
            if (item == null)
            {
                itemList.Add(itemVM.CurrentItem);
            }
        }

        itemVM.Cleanup();
    }

また、itemView XAML には DataContext へのバインドがありません。そうしないと、ViewModel の 2 つの異なるインスタンスが作成されます。

Window タグ内。ShowDialog で結果を取得するには、DialogCloser コードを使用します。

    public static class DialogCloser
    {
        public static readonly DependencyProperty DialogResultProperty =
            DependencyProperty.RegisterAttached(
                "DialogResult",
                typeof(bool?),
                typeof(DialogCloser),
                new PropertyMetadata(DialogResultChanged));

        private static void DialogResultChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var window = d as Window;
            if (window != null)
                window.DialogResult = e.NewValue as bool?;
        }

        public static void SetDialogResult(Window target, bool? value)
        {
            target.SetValue(DialogResultProperty, value);
        }
    }

ItemView では、これは次のように Window タグ内で宣言されます。

my:DialogCloser.DialogResult="{Binding DialogResult}"

また、ダイアログが閉じられると、終了イベントによって DialogResult が true または false に設定されます。

これは、初めて画面を開いたときは完全に機能しますが、ダイアログを閉じた後に再度開くことはできません。

ダイアログを開くためのより良いアイデアがあるかどうか、およびこのコードが機能しない理由を知りたいです。

ありがとう!

編集: 私はすでにコードを修正しました。私がする必要があるのは、新しい ViewModel を作成し、ダイアログが開かれるたびにそれを DataContext にアタッチすることです。さらに、XAML から DataContext バインディングを削除する必要がありました。上記のコードの変更を確認してください。

これらの変更により、ViewModelLocator から ViewModel を使用できないことがわかりました。これは、新しいウィンドウごとに新しいインスタンスではなく「シングルトン」であるためです。したがって、DialogResult は最後の値を保持し、その値を null に戻そうとすると (ViewModel が初期化されたときのように) 例外がスローされます。なぜこれが起こるのか手がかりはありますか?システム全体で同じ戦略を維持できるため、ViewModelLocator から ViewModel を使用することは私にとって非常に良いことです。

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

4

2 に答える 2

0

これを行うには、たとえば NewUser(); などのメソッドが呼び出される静的な XxxxInteraction クラスを実装します。そのメソッドはダイアログを開き、いくつかの作業を行います。私の ViewModel では、コマンドを介して XxxxInteraction クラスを呼び出します。

その実装方法の努力は、UnitTests を使用するために静的な相互作用クラスのメソッドを簡単に変更できることです。

    public static class UserInteractions
    {
        public static User NewUser()
        {
            var userDialog = new NewUserDialog();
            If(userDialog.ShowDialog() != true) return null;

            var user = new User();
            user.Name = userDialog.Name;
            user.Age = userDialog.Age;
            return user;
        }
    }

    public class MyViewModel
    {
        ...

        public void NewUserCommandExecute()
        {
            var newUser = UserInteractions.NewUser();
            if(newUser == null) return;

            //Do some with new created user
        }
    }

NewUserDialog は、ViewModel にもバインドされている通常の Window です。

これは、mvvm パターンのダイアログを実装する良い方法だと思います。

于 2012-08-06T19:18:14.487 に答える
0

私はこれを少し前に行いました。ダイアログ サービスを使用し、ビューモデルでこのサービスを呼び出します。見てください

編集:ところで、ビューモデルで行う必要があるのはそれだけです

var result = this.uiDialogService.ShowDialog("Dialogwindow title goes here", dialogwindowVM);
于 2012-08-07T05:28:38.140 に答える