Как добавить триггер события в шаблон данных для бизнес-объекта? - PullRequest
2 голосов
/ 14 сентября 2009

У меня есть собственный класс с именем BlinkingLight. У меня также есть статическая ObservableCollection BlinkingLightCollection. В пользовательском интерфейсе у меня есть ListBox, который связан с BlinkingLightCollection.

В моем ListBox я хочу по существу отобразить каждый объект BlinkingLight в качестве пользовательского элемента управления, который выглядит как блок со светодиодной подсветкой, с анимацией, которая заставляет светодиод выглядеть так, как будто он просто мигает на секунду, а затем возвращается в нормальное состояние.

В моем классе BlinkingLight есть сторонний объект «LED», который вызывает событие «Flash».

Я ищу идеи или решения, чтобы заставить это работать!

Моя неудачная попытка:

Я создал пользовательский элемент управления (BlinkingLightControl), который может связываться с данными моего класса BlinkingLight, когда BlinkingLight является DataContext моего настраиваемого элемента управления.

Я создал шаблон данных для моего ListBox:

<Window.Resources>
  <DataTemplate x:Key="blinkingLightItemTemplate" >
    <local:BlinkingLightControl />
  </DataTemplate>
</Window.Resources>

<ListBox ItemsSource={Binding Source={x:Static local:Data.BlinkingLightCollection}}
         ItemTemplate="{StaticResource blinkingLightItemTemplate}" />

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

Теперь я хочу, чтобы в моем BlinkingLightControl (или DataTemplate) был EventTrigger, для которого RoutedEvent является событием LED.Flash. К сожалению, я не могу понять эту часть. Я попытался создать RoutedEvent в своем классе BlinkingLight и просто вызывать его всякий раз, когда я обрабатываю событие LED.Flash. Однако мой класс не является UIElement или ContentElement, и для каждого MSDN: MSND Link

"Владельцем перенаправленного события может быть любой класс, но перенаправленные события должны вызываться и обрабатываться производными классами UIElement или ContentElement, чтобы быть полезными. Для получения дополнительной информации о пользовательских событиях см. Практическое руководство. Создание настраиваемого перенаправленного события . "

Любая помощь будет принята с благодарностью! Спасибо, Скотт

Ответы [ 3 ]

2 голосов
/ 22 сентября 2009

Мне удалось найти решение, которое работало достаточно хорошо:

Поскольку мой DataTemplate просто содержит пользовательский UserControl (который привязывается к DataContext для получения своих данных из бизнес-объекта) ... я поместил свой пользовательский RoutedEvent в UserControl. Затем в загруженном событии моего UserControl я приводил DataContext в качестве моего бизнес-объекта, чтобы получить доступ к свойству бизнес-объекта, в котором есть событие, и подключил его к обработчику события. (в моем примере я приводил DataContext как объект BlinkingLight, затем я могу получить доступ к событию Flash его свойства Led и подключить его к пользовательскому обработчику событий). Примечание: объект LED должен быть свойством, а не просто полем в объекте BlinkingLight, чтобы он работал.

Затем обработчик события может вызвать пользовательское перенаправленное событие UserControl (FlashGreenEvent). Ниже приведен внутренний код, который теперь дополняет код в OP (я удалил любой другой нерелевантный код).

public partial class BlinkingLightControl : UserControl
{
    public static readonly RoutedEvent FlashGreenEvent = EventManager.RegisterRoutedEvent("FlashGreen", RoutingStrategy.Direct, typeof(RoutedEventHandler), typeof(BlinkingLightControl));
    public event RoutedEventHandler FlashGreen
    {
        add { AddHandler(FlashGreenEvent, value); }
        remove { RemoveHandler(FlashGreenEvent, value); }
    }

    private void BlinkingLightControl_Loaded(object sender, RoutedEventArgs e)
    {
        BlinkingLight blinkingLight = (BlinkingLight)this.DataContext;

        blinkingLight.Led.Flash += LED_Flash;
    }

    protected delegate void LED_FlashCallback(ThirdParty.LED sender);
    public void LED_Flash(ThirdParty.LED sender)
    {
        if (this.Dispatcher.CheckAccess())
        {
            // Raise the Flash Green Event;
            RaiseEvent(new RoutedEventArgs(BlinkingLightControl.FlashGreenEvent));
        }
        else
            this.Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, new LED_FlashCallback(LED_Flash), sender);
    }
}
2 голосов
/ 15 сентября 2009

В этом случае лучший способ - использовать WPF Commanding и создать RoutedCommand BlinkTheLights - ваш BlinkingLightControl будет обрабатывать команду BlinkTheLights и отвечать, запустив StoryBoard, которая будет мигать.

1 голос
/ 17 мая 2010

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

что-то вроде:

  <Style TargetType="{x:Type local:MyControl}">

  <!-- fade in the control with an animation -->
  <Style.Triggers>
    <EventTrigger RoutedEvent="Control.Loaded">
      <BeginStoryboard>
        <Storyboard>
         <DoubleAnimation To="1" Duration="0:0:1" Storyboard.TargetProperty="Opacity"/>
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Style.Triggers>

  <!-- Make sure the opacity starts at 0 -->
  <Setter Property="Opacity" Value="0"/>
  <Setter Property="Template">
      <Setter.Value>
         <ControlTemplate TargetType="{x:Type local:MyControl}">
         </ControlTemplate>
      </Setter.Value>
  </Setter>
</Style>
...