我有一个名为BlinkingLight的自定义类。 我还有一个静态的ObservableCollection BlinkingLightCollection。 在UI中,我有一个绑定到BlinkingLightCollection的ListBox。
在我的ListBox中,我想基本上将每个BlinkingLight对象显示为一个自定义控件,它看起来像带有LED灯的盒子,其动画使得LED看起来只是闪烁一秒,然后恢复正常。 / p>
我的BlinkingLight类有第三方“LED”对象,它会引发一个名为“Flash”的事件。
我正在寻找想法或解决方案来实现这一目标!
我尝试失败:
我创建了一个自定义控件(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放入datatemplate,而不是让它更容易控制。
现在我希望在我的BlinkingLightControl(或DataTemplate)中有一个EventTrigger,其中RoutedEvent是LED.Flash事件。不幸的是,我似乎无法弄清楚这一部分。我试图在我的BlinkingLight类中创建一个RoutedEvent,只要我处理LED.Flash事件就把它抬起来。但是,我的课程不是UIElement或ContentElement,而是根据MSDN:MSND Link
“路由事件所有者可以是任何类,但路由事件必须由UIElement或ContentElement派生类引发并处理才能有用。有关自定义事件的详细信息,请参阅如何:创建自定义路由事件。“
任何帮助将不胜感激!! 谢谢, 斯科特
答案 0 :(得分:2)
在这种情况下,最好的方法是使用WPF命令并创建一个“BlinkTheLights”RoutedCommand - 您的BlinkingLightControl将处理BlinkTheLights命令,并通过启动一个使灯闪烁的StoryBoard进行响应。
答案 1 :(得分: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);
}
}
答案 2 :(得分:1)
如果您正在制作自定义控件,则始终可以在控件模板之外设置触发器。
类似的东西:
<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>