Как вызвать метод в окне (.xaml.cs) из viewmodel (.cs) без ввода новых ссылок в wpf

Я ищу простой способ вызова метода в своем главном окне, но я хочу назвать его из моей модели просмотра. В принципе, я ищу кого-то из этого типа "this.parent", чтобы поместить в модель View ссылку на главное окно.

Или, если вы хотите проверить причину, по которой я хочу это сделать, и сказать мне другой способ решить мою проблему:

Я работаю с приложением, которое постоянно получает информацию, поданную на него. В viewmodel информация обрабатывается. Я хочу получать уведомление каждый раз, когда приходит информация, которая удовлетворяет некоторой квалификации.

Изначально у меня был словарь в режиме просмотра, в котором хранилась информация об этой информации, и я получил доступ к этому словарю в MainWindow, чтобы я мог сделать окно flash и отправить другие уведомления. Но у меня возникали проблемы с постоянным изменением словаря в режиме просмотра, когда я обращался к нему в MainWindow.

Извините, если этот вопрос звучит глупо. Я только начал работать с WPF два месяца назад и не имел большого опыта программирования даже до этого.

Ответ 1

VM не должна "ничего не знать" о вашем представлении или окне, то, как виртуальная машина обычно "обменивается" с V в WPF/MVVM, - это события с расширением. Таким образом, VM остается неосведомленной/отсоединенной от V, и поскольку VM уже DataContext V, не трудно подписаться на событие VM.

Пример:

VM:

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

В:

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

private void DoSomething(object sender, NotificationEventArgs<string> e)
{
    // Code    
}

Ответ 2

прежде всего, это не глупый вопрос. Большинство стартеров MVVM пришли из winforms, и это нормально, чтобы иметь тенденцию приводить ваши методы winforms и работать над кодом. Теперь все, что вам нужно сделать, это забыть об этом и подумать о MVVM.

Возвращаясь к вашему вопросу, у вас есть словарь, который ваша VM обрабатывает, и вы получаете доступ к этому словарю из представления. Ваш взгляд не должен иметь никакого представления о вашей модели просмотра, кроме как через привязку.

Создание окна flash, когда изменения в режиме просмотра звучат как привязанное поведение ко мне. Здесь хорошо читается о приложенном поведении. 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, вы получите сообщение с уведомлением пользователя о том, что что-то было добавлено в вашу коллекцию.

Я надеюсь, что помог в вашей проблеме. Просто скажите, нужны ли вам какие-то разъяснения.