2

我有一个名为 BlinkingLight 的自定义类。我还有一个静态 ObservableCollection BlinkingLightCollection。在 UI 中,我有一个绑定到 BlinkingLightCollection 的 ListBox。

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

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

我正在寻找想法或解决方案来让它发挥作用!

我失败的尝试:

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

我为我的 ListBox 创建了一个 DataTemplate:

<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 事件。不幸的是,我似乎无法弄清楚这部分。我试图在我的 BlinkingLight 类中创建一个 RoutedEvent ,并在我处理 LED.Flash 事件时引发它。但是,我的课程不是 UIElement 或 ContentElement,并且根据 MSDN:MSND Link

“路由事件所有者可以是任何类,但路由事件必须由 UIElement 或 ContentElement 派生类引发和处理才能有用。有关自定义事件的更多信息,请参阅如何:创建自定义路由事件。”

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

4

3 回答 3

2

我能够想出一个效果很好的解决方案:

由于我的 DataTemplate 只包含一个自定义 UserControl(它绑定到 DataContext 以从业务对象获取其数据)...我将自定义 RoutedEvent 放在 UserControl 中。然后在我的 UserControl 的加载事件中,我将 DataContext 转换为我的业务对象,以访问具有该事件的业务对象的属性并将其连接到事件处理程序。(在我的示例中,我将 DataContext 转换为 BlinkingLight 对象,然后我可以访问其 Led 属性的 Flash 事件并将其连接到自定义事件处理程序)。注意: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);
    }
}
于 2009-09-21T20:55:34.857 回答
2

在这种情况下,最好的方法是使用 WPF 命令并创建一个“BlinkTheLights”RoutedCommand - 您的 BlinkingLightControl 将处理 BlinkTheLights 命令,并通过启动一个让灯闪烁的 StoryBoard 来响应。

于 2009-09-15T02:19:05.890 回答
1

If you're making a custom control you could always set the trigger outside of the control template.

something like:

  <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>
于 2010-05-17T14:50:47.470 回答