代码之家  ›  专栏  ›  技术社区  ›  Scott

如何将事件触发器添加到业务对象的数据模板中?

  •  2
  • Scott  · 技术社区  · 16 年前

    我有一个名为BlinkingLight的自定义类。 我也有一个静态的ObservableCollection BlinkingLightCollection。

    在我的列表框中,我希望基本上将每个BlinkingLight对象显示为一个自定义控件,该控件看起来像一个带有LED灯的框,该LED灯有一个动画,使LED看起来像刚刚闪烁了一秒钟,然后恢复正常。

    我的BlinkingLight类具有第三方“LED”对象,该对象引发一个名为“Flash”的事件。

    我正在寻找想法或解决方案,使这项工作!

    我失败的尝试:

    我创建了一个自定义控件(BlinkingLightControl),当BlinkingLight是自定义控件的DataContext时,它可以绑定到BlinkingLight类的数据。

    我为我的列表框创建了一个数据模板:

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

    注意:我可以将自定义控件的xaml放在datatemplate中,而不是使用完全不同的控件,如果这样做可以使事情变得更简单的话。

    现在我想在我的BlinkingLightControl(或DataTemplate)中有一个EventTrigger,谁的RoutedEvent是LED.Flash事件。不幸的是,我似乎无法理解这一部分。我尝试在我的BlinkingLight类中创建一个RoutedEvent,并在处理LED.Flash事件时将其升高。但是,我的类不是UIElement或ContentElement,根据MSDN: MSND Link

    任何帮助都将不胜感激!! 斯科特

    3 回复  |  直到 13 年前
        1
  •  2
  •   Ana Betts    16 年前

    在这种情况下,最好的方法是使用WPF命令并创建一个“BlinkTheLights”路由命令-您的BlinkingLights控件将处理BlinkTheLights命令,并通过启动一个情节提要来响应,该情节提要会使灯光闪烁。

        2
  •  2
  •   Scott    16 年前

    我能够想出一个非常有效的解决方案:

    因为我的DataTemplate只包含一个自定义UserControl(它绑定到DataContext以从业务对象获取数据)。。。我将自定义RouteEvent放在UserControl中。然后在UserControl的loaded事件中,我将DataContext转换为我的业务对象,以访问包含该事件的业务对象的属性,并将其连接到事件处理程序。(在我的示例中,我将DataContext强制转换为一个BlinkingLight对象,然后我可以访问其Led属性的Flash事件,并将其连接到自定义事件处理程序)。 注意:LED对象必须是属性,而不仅仅是BlinkingLight对象中的字段才能工作。

    然后事件处理程序可以引发UserControl的自定义路由事件(FlashGreeneEvent)。下面是后端代码,它现在补充了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);
        }
    }
    
        3
  •  1
  •   Andy    16 年前

    如果要创建自定义控件,则始终可以在控件模板之外设置触发器。

    比如:

      <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>