Question

J'ai une classe personnalisée nommée BlinkingLight. J'ai aussi un ObservableCollection statique BlinkingLightCollection. Dans l'interface utilisateur, j'ai un ListBox lié à BlinkingLightCollection.

Dans mon ListBox, je souhaite essentiellement afficher chaque objet BlinkingLight sous la forme d'un contrôle personnalisé ressemblant à un boîtier avec une lumière LED avec une animation qui donne l'impression que la LED a clignoté pendant une seconde puis est revenue à la normale.

Ma classe BlinkingLight est associée à une "LED" tierce. objet qui déclenche un événement appelé 'Flash'.

Je cherche des idées ou des solutions pour que cela fonctionne!

Ma tentative a échoué:

J'ai créé un contrôle personnalisé (BlinkingLightControl) pouvant se lier aux données de ma classe BlinkingLight lorsqu'un BlinkingLight est le DataContext de mon contrôle personnalisé.

J'ai créé un DataTemplate pour mon ListBox:

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

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

Remarque: je peux simplement insérer le xaml de mon contrôle personnalisé dans le modèle de données à la place d'un contrôle complètement différent si cela facilite les choses.

Maintenant, je veux avoir un EventTrigger dans BlinkingLightControl (ou DataTemplate) qui est RoutedEvent est l'événement LED.Flash. Malheureusement, je n'arrive pas à comprendre cette partie. J'ai essayé de créer un événement RoutedEvent dans ma classe BlinkingLight et de le relever chaque fois que je gère l'événement LED.Flash. Toutefois, ma classe n’est ni UIElement ni ContentElement, et selon MSDN: Lien MSND

"Le propriétaire de l’événement routé peut être n’importe quelle classe, mais les événements routés doivent être générés et gérés par les classes dérivées UIElement ou ContentElement pour être utiles. Pour plus d'informations sur les événements personnalisés, voir Procédure: créer un événement routé personnalisé. "

Toute aide serait grandement appréciée !! Merci, Scott

Était-ce utile?

La solution 2

J'ai pu trouver une solution qui a très bien fonctionné:

Étant donné que mon DataTemplate contient simplement un UserControl personnalisé (qui se lie au DataContext pour extraire ses données de l'objet métier) ... j'ai placé mon événement RoutedEvent personnalisé dans UserControl. Ensuite, dans l'événement chargé de mon UserControl, je convertis le DataContext en tant qu'objet métier pour accéder à la propriété de l'objet métier associée à l'événement et le relier à un gestionnaire d'événements. (Dans mon exemple, je transtypage le DataContext en tant qu'objet BlinkingLight, puis je peux accéder à l'événement Flash de sa propriété Led et le relier à un gestionnaire d'événements personnalisé). Remarque: L’objet LED doit être une propriété, et pas seulement un champ de l’objet BlinkingLight, pour que cela fonctionne.

Ensuite, le gestionnaire d'événements peut générer l'événement routé personnalisé de UserControl (FlashGreenEvent). Ci-dessous se trouve le code d’arrière-plan qui complète maintenant le code de l’OP (j’ai supprimé tout autre code non pertinent).

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);
    }
}

Autres conseils

Dans ce cas, le meilleur moyen consiste à utiliser WPF Command et à créer un "BlinkTheLights". RoutedCommand - votre BlinkingLightControl gérera la commande BlinkTheLights et répondra en démarrant un StoryBoard qui clignotera.

Si vous créez un contrôle personnalisé, vous pouvez toujours définir le déclencheur en dehors du modèle de contrôle.

quelque chose comme:

  <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>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top