Как вызвать метод в окне (.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, вы получите сообщение с уведомлением пользователя о том, что что-то было добавлено в вашу коллекцию.
Я надеюсь, что помог в вашей проблеме. Просто скажите, нужны ли вам какие-то разъяснения.