17

メイン ウィンドウでメソッドを呼び出す簡単な方法を探していますが、View Model から呼び出したいと考えています。基本的に、メイン ウィンドウを参照するためにビュー モデルに配置する「this.parent」のようなものを探しています。

または、私がこれをやりたい理由を確認したい場合は、私の問題に対処する別の方法を教えてください。

私は常に情報を受け取るアプリを使用しています。ビューモデルでは、情報が処理されます。一定の条件を満たす情報が入ってくるたびに通知したい。

最初は、その情報に関する情報を保存するビューモデルに辞書があり、MainWindow でその辞書にアクセスして、ウィンドウを点滅させて他の通知を送信できるようにしました。しかし、MainWindow でアクセスしているときにビューモデルの辞書が継続的に変更されるという問題が発生していました。

この質問が愚かに聞こえる場合は申し訳ありません。私は 2 か月前に WPF を使い始めたばかりで、それ以前からプログラミングのバックグラウンドも十分ではありませんでした。

4

2 に答える 2

32

VM は、ビューまたはウィンドウについて何も「認識」する必要はありません。VM が通常、WPF/MVVM で V と「通信」する方法は、イベントを発生させることです。そうすれば、VM は V を認識しない/V から切り離されたままになり、VM はすでにDataContextV であるため、VM のイベントをサブスクライブすることは難しくありません。

例:

仮想マシン:

public event EventHandler<NotificationEventArgs<string>> DoSomething;
...
Notify(DoSomething, new NotificationEventArgs<string>("Message"));

V:

var vm = DataContext as SomeViewModel; //Get VM from view's DataContext
if (vm == null) return; //Check if conversion succeeded
vm.DoSomething += DoSomething; // Subscribe to event

private void DoSomething(object sender, NotificationEventArgs<string> e)
{
    // Code    
}
于 2013-11-07T23:09:38.857 に答える
14

まず第一に、それはばかげた質問ではありません。ほとんどの MVVM スターターは winforms から来ており、winforms のプラクティスを取り入れてコード ビハインドに取り組む傾向があるのは普通のことです。あとは、それを忘れて MVVM を考えるだけです。

質問に戻ると、VM が処理している辞書があり、ビューからその辞書にアクセスしています。ビューは、バインディングを介する場合を除いて、ビューモデルについて何も考えてはいけません。

ビューモデルに変更があったときにウィンドウを点滅させることは、私には付属の動作のように聞こえます。ここでは、添付された動作についてよく読んでください。 http://www.codeproject.com/Articles/28959/Introduction-to-Attached-Behaviors-in-WPF

簡単にするために、あなたのケースに何らかの形で関連する非常に単純な例を挙げようと思います。

何かを追加するたびにメッセージボックスが画面に表示される IEnumerable があるアタッチされた動作クラスを作成します。メッセージボックスのコードを、通知時に実行したい点滅アニメーションに変更するだけです。

public class FlashNotificationBehavior
{
    public static readonly DependencyProperty FlashNotificationsProperty =
        DependencyProperty.RegisterAttached(
        "FlashNotifications",
        typeof(IEnumerable),
        typeof(FlashNotificationBehavior),
        new UIPropertyMetadata(null, OnFlashNotificationsChange));

    private static void OnFlashNotificationsChange(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var collection = e.NewValue as INotifyCollectionChanged;

        collection.CollectionChanged += (sender, args) => 
            {
                if (args.Action == NotifyCollectionChangedAction.Add)
                {
                    foreach (var items in args.NewItems)
                        MessageBox.Show(items.ToString());
                }
            };            
    }

    public static IEnumerable GetFlashNotifications(DependencyObject d)
    {
        return (IEnumerable)d.GetValue(FlashNotificationsProperty);
    }

    public static void SetFlashNotifications(DependencyObject d, IEnumerable value)
    {
        d.SetValue(FlashNotificationsProperty, value);
    }
}

ビューモデルでは、ObservableCollection プロパティを作成できます。監視可能なコレクションが必要なので、コレクション変更イベント通知があります。テストできるように、追加するためのコマンドも追加しました。

   public class MainViewModel : ViewModelBase
{
    ObservableCollection<string> notifications;

    public ObservableCollection<string> Notifications
    {
        get { return notifications; }
        set
        {
            if (notifications != value)
            {
                notifications = value;
                base.RaisePropertyChanged(() => this.Notifications);
            }
        }
    }

    public ICommand AddCommand
    {
        get
        {
            return new RelayCommand(() => this.Notifications.Add("Hello World"));
        }
    }

    public MainViewModel()
    {
        this.Notifications = new ObservableCollection<string>();             
    }
}

ビューモデルから通知プロパティにバインドできるビューを次に示します。

<Window x:Class="WpfApplication7.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:WpfApplication7.ViewModel"
    xmlns:local="clr-namespace:WpfApplication7"
    Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
    <vm:MainViewModel />
</Window.DataContext>
<Grid>
    <StackPanel>
        <ListBox ItemsSource="{Binding Notifications}" 
                 local:FlashNotificationBehavior.FlashNotifications="{Binding Notifications}"></ListBox>
        <Button Command="{Binding AddCommand}" >Add Something</Button>
    </StackPanel>
</Grid>

ObservableCollection に何かを追加するたびに、コレクションに何かが追加されたことをユーザーに通知するメッセージ ボックスが表示されます。

私はあなたの問題に役立ったことを願っています。説明が必要な場合は教えてください。

于 2013-11-08T00:47:41.840 に答える