web-dev-qa-db-ja.com

wpfに新しい参照を導入せずにビューモデル(.cs)からウィンドウ(.xaml.cs)でメソッドを呼び出す方法

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

または、私がこれを実行したい理由を確認して、問題を解決する別の方法を教えてください。

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

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

この質問が愚かに聞こえたら申し訳ありません。 2か月前にWPFを始めたばかりで、それ以前にもプログラミングの優れた背景がありませんでした。

16
user2879853

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

例:

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    
}
32
Dean Kuga

まず第一に、それは愚かな質問ではありません。 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に何かを追加するたびに、コレクションに何かが追加されたことをユーザーに通知するメッセージボックスが表示されます。

私があなたの問題を助けてくれたことを願っています。いくつかの説明が必要かどうか教えてください。

14
Lance