Ответ 1
Спасибо за то, что вы указали свой вопрос.
Используйте поведение blend и существующие триггеры и действия для выполнения требования Tomas:
У меня довольно простая (я надеюсь:)) проблема:
В MVVM View обычно прослушивает изменения свойств ViewModel. Тем не менее, мне иногда хотелось слушать событие, так что, например, View мог бы начать анимацию или закрыть окно, когда сигналы VM.
Выполнение этого с помощью свойства bool с NotifyPropertyChanged (и запуск анимации только при изменении от false до true) возможно, но это похоже на хак, я бы предпочел разоблачить событие, поскольку оно семантически корректно.
Кроме того, я хотел бы сделать это без кода в codebehind, так как do viewModel.myEvent += handler
означало бы, что я бы вручную отменил регистрацию события, чтобы позволить View быть GC'd - WPF Views уже доступны для слабого прослушивания свойств, и я бы предпочел программировать только декларативно в представлении.
Стандартная подписка на сильное событие также плоха, потому что мне нужно переключить несколько ViewModels для одного представления (потому что при создании View каждый раз требуется слишком много времени процессора).
Спасибо за идеи (если есть стандартное решение, достаточно ссылки на msdn)!
Спасибо за то, что вы указали свой вопрос.
Используйте поведение blend и существующие триггеры и действия для выполнения требования Tomas:
Некоторые комментарии:
Этот поток довольно старый, но я предоставил свои $0,02, потому что это то, с чем я боролся, а также недавно...
Подобно тому, что говорят другие, но вот пример с некоторыми фрагментами кода... В этом примере показано, как использовать pub/sub, чтобы иметь возможность подписываться на событие, выпущенное виртуальной машиной, - в этом случае я делаю Вид сетки. Восстановите, чтобы gv синхронизировался с VM...
Просмотр (Sub):
using Microsoft.Practices.Composite.Events;
using Microsoft.Practices.Composite.Presentation.Events;
private SubscriptionToken getRequiresRebindToken = null;
private void SubscribeToRequiresRebindEvents()
{
this.getRequiresRebindToken =
EventBus.Current.GetEvent<RequiresRebindEvent>()
.Subscribe(this.OnRequiresRebindEventReceived,
ThreadOption.PublisherThread, false,
MemoryLeakHelper.DummyPredicate);
}
public void OnRequiresRebindEventReceived(RequiresRebindEventPayload payload)
{
if (payload != null)
{
if (payload.RequiresRebind)
{
using (this.gridView.DeferRefresh())
{
this.gridView.Rebind();
}
}
}
}
private void UnsubscribeFromRequiresRebindEvents()
{
if (this.getRequiresRebindToken != null)
{
EventBus.Current.GetEvent<RequiresRebindEvent>()
.Unsubscribe(this.getRequiresRebindToken);
this.getRequiresRebindToken = null;
}
}
Вызовите unsub из метода закрытия, чтобы предотвратить утечку памяти.
ViewModel (Pub):
private void PublishRequiresRebindEvent()
{
var payload = new RequiresRebindEventPayload();
payload.SetRequiresRebind();
EventBus.Current.GetEvent<RequiresRebindEvent>().Publish(payload);
}
Класс полезной нагрузки
using System;
using Microsoft.Practices.Composite.Presentation.Events;
public class RequiresRebindEvent
: CompositePresentationEvent<RequiresRebindEventPayload>
{
}
public class RequiresRebindEventPayload
{
public RequiresRebindEventPayload()
{
this.RequiresRebind = false;
}
public bool RequiresRebind { get; private set; }
public void SetRequiresRebind()
{
this.RequiresRebind = true;
}
}
Обратите внимание, что вы также можете установить конструктор для передачи в Guid или некоторые из них, которые могут быть установлены на Pub и проверены на sub, чтобы убедиться, что pub/sub синхронизирован.
imho yY и разделенные
В то время как верно, что вы можете сделать это с привязкой к свойствам, это больше похоже на хак, как упомянутые tomas; всегда так чувствовал это.
Мое решение, чтобы иметь возможность прослушивать "события" из модели просмотра, а также уведомления, - это просто прослушивать изменения контекста данных, а когда он меняет, я проверяю тип - это vm, который я ищу и подключаю к событиям, сырой, но простой.
что мне очень нравится, это простой способ определить некоторые триггеры событий модели представления, а затем предоставить какой-то обработчик для него, который будет реагировать на сторону всех вещей в xaml и только отбросить код за материал, который не работает в xaml
Как и Adrianm, когда вы запускаете свою анимацию из свойства bool, вы фактически отвечаете на событие. В частности, событие PropertyChanged
, которое подсистема WPF. Который предназначен для правильной установки/отсоединения, чтобы вы не просачивали память (вы можете забыть это сделать при проводке события самостоятельно и вызвать утечку памяти путем ссылки на объект, который в противном случае должен быть GCed),
Это позволяет вам отображать ViewModel как DataContext
для элемента управления и правильно реагировать на изменение свойств в datacontext посредством привязки данных.
MVVM - это шаблон, который особенно хорошо работает с WPF из-за всех этих вещей, которые дает WPF, и выключение изменения свойств на самом деле является изящным способом использования всей подсистемы WPF для достижения ваших целей:)
Более общий вопрос: "Почему я пытаюсь разобраться с этим событием в моей модели ViewModel?"
Если ответ имеет какое-то отношение к объектам, похожим только на просмотр, например анимация, я бы сказал, что ViewModel не должен знать об этом: код позади (когда это необходимо), Data/Event/PropertyTriggers и новые конструкции VisualStateManager будут служить вы намного лучше и поддерживаете чистое разделение между View и ViewModel.
Если что-то должно "произойти" в результате события, то то, что вы действительно хотите использовать, - это шаблон команды - либо с помощью CommandManger, обработки события в коде позади и вызова команды в модели представления, или используя прикрепленные поведения в библиотеках System.Interactivity.
В любом случае, вы хотите, чтобы ваш ViewModel был "чистым", как вы можете, - если вы видите что-то видимое в нем, вы, вероятно, ошибаетесь.:)