2013-07-25 5 views
2

У меня есть класс, MyAttachedEventClassAquarium, который определяет пользовательскую привязку, взятую из документации MSDN. У меня есть Window, который использует EventTrigger в XAML, чтобы связать событие, которое нужно обработать на модели просмотра Window. Модель viewmodel объявлена ​​как локальный ресурс.Подключенные события с EventTrigger

<Window.Resources> 
    <local:WinVM x:Key="myWinVM" /> 
</Window.Resources> 
<i:Interaction.Triggers> 
    <i:EventTrigger EventName="NeedsCleaning" SourceName="MyAttachedEventClassAquarium"> 
     <ei:CallMethodAction MethodName="MyCustomEventWasRaised" TargetObject="{StaticResource myWinVM}" /> 
    </i:EventTrigger> 
</i:Interaction.Triggers> 

Я использую собственный RaiseEvent окна, чтобы поднять прилагаемое событие от нажатия кнопки обработчика:

private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     ((Window1)((Grid)((Button)sender).Parent).Parent).RaiseEvent(new RoutedEventArgs(MyAttachedEventClassAquarium.NeedsCleaningEvent)); 
    } 

Почему не мой обработчик можно назвать?

Заранее спасибо.

B.

+0

Вы проверили окно вывода на наличие ошибок? – whoisthis

+0

Да. В окне вывода не было ошибок. – Balage

ответ

0

(Edited)

Такой подход к закреплять события для ViewModel, чтобы процесс выглядит маловероятным, чтобы быть ремонтопригодны. Для устранения неполадок может быть хорошей идеей использовать утилиту Snoop для разделения визуальных и логических деревьев, чтобы убедиться, что объекты, которые вы выполняете, все из которых реализуют метод RaiseEvent, на самом деле являются объектами, которые вы хотите.

Возможно, вам также потребуется определить параметр SourceName как ресурс в вашем окне.

Это догадки, и они описывают совсем другой подход к передаче сообщений, чем обращаются к шаблонам MVVM. Вместо того, чтобы копаться в вашем логическом дереве, таком как очень хрупкий подход, используйте документированные и проверенные шаблоны, найденные ниже и в другом месте: Войдите в DataContext вашего Window и вызовите метод виртуальной машины напрямую. Или, реализуйте ICommand в вашем классе ViewModel и свяжите с ним команды.

Этот первый подход разбивает самые чистые подходы к MVVM, но он будет работать.

private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     var VM = this.DataContext As WinVM; 

     if (VM != null) 
     { 
     VM.MyCustomEventWasRaised(); 
     } 
    } 

Другой подход реализовать ICommand на классе ViewModel и настроить Button в представлении использовать команду:

<Button x:Name="Button1" Command="{Binding NeedsCleaning}" /> 

Этот последний устранит необходимость для любого XAML кода позади кода в большинстве случаев.

+0

Извините, я должен был быть более ясным, что поднятие механики событий было второстепенным в этом случае. Мне было бы интересно, почему, подняв прикрепленное событие на экземпляре окна, которое является частью визуального дерева, не вызвало обработчик, объявленный в части EventTrigger XAML. – Balage

+0

Никогда не видел, чтобы кто-то подходил к сообщениям ViewModel таким образом, я не могу сказать. Я отредактировал ответ с некоторыми комментариями, которые могут помочь. –

0

Мне кажется, что проблема SourceName - это должен быть экземпляр, а не имя класса? Если добавить источник событий в визуальном дереве как «аквариум», и изменить «SourceName» в «аквариуме», то действие сработал:

<Window> 
    <Window.Resources> 
     <local:WinVM x:Key="myWinVM" /> 
    </Window.Resources> 
    <i:Interaction.Triggers> 
     <i:EventTrigger EventName="NeedsCleaning" SourceName="aquarium"> 
      <ei:CallMethodAction MethodName="MyCustomEventWasRaised" TargetObject="{StaticResource myWinVM}" /> 
     </i:EventTrigger> 
    </i:Interaction.Triggers> 

    <StackPanel> 
     <my:MyAttachedEventClassAquarium x:Name="aquarium" /> 
     <Button x:Name="button" Click="button1_Click" Content="Raise Event" /> 
    </StackPanel> 

</Window> 

private void button1_Click(object sender, RoutedEventArgs e) 
{ 
    aquarium.RaiseEvent(new RoutedEventArgs(MyAttachedEventClassAquarium.NeedsCleaningEvent)); 
} 

Просто добавить : вышеприведенный подход работает только, если я оба поднимаю событие на объект аквариума, а также используют тот же объект аквариума, что и EventTrigger's SourceName. Кажется, что это связано с классом System.Windows.Interactivity.EventTrigger (ошибка?), Потому что, когда я использую класс DependencyObject.Triggers.EventTrigger, событие пузырится, как и следовало ожидать.

 Смежные вопросы

  • Нет связанных вопросов^_^