none
RoutedEvent in ControlTemplate nur für "eigenes" Element RRS feed

  • Frage

  • Hallo allerseits,

    folgende Frage: ich verwende ich einem TreeViewItem-ControlTemplate das Event "TreeViewItem.Expanded". Wird dieses nun aufgerufen, reagieren hierauf auch alle übergeordneted TreeViewItems (da ja ein RoutedEvent). Nun könnte ich bei jedem TreeViewItem im Expanded-Event den Wert "handled" auf "true" setzen - aber ist das wirklich die Lösung?

    Grüße,

    Tristan
    Mittwoch, 10. März 2010 11:47

Antworten

Alle Antworten

  • Hi Tristan,

    das von Dir angesprochene Verhalten ist das sogenannte "Bubbling". Sprich, solange der Event nicht abgehandelt ist, wird dieser weiter nach oben (zum jew. Parent) gereicht. Wenn Du etwas á la lazy loading implementieren willst, schau Dir mal z.B. diesen Thread an. Ansonsten beschreibe mal genauer, was Du vorhast, am besten mit einem Beispiel-Window, das sich ausführen lässt.
    Cheers,
    Olaf
    http://blogs.intuidev.com
    Mittwoch, 10. März 2010 12:13
  • Hey Olaf,

    danke für deine schnelle Antwort!

    Ich möchte die untergeordneten Items (den Itemspresenter) nicht einfach einfach anzeigen / verbergen, sondern per ScaleTransform den y-Wert von 0-1 bzw. 1-0 animieren. Alternativ könnte ich hierfür auch per Setter (Enter / Exit Action) den Wert "IsExpanded" verwenden, hätte es aber gerne mit einem EventTrigger gelöst. Derzeit werden (wie du schon gemeint hast: bubbling) auch alle übergeordneten Elemente mit minimiert / maximiert.

     

    <EventTrigger RoutedEvent="TreeViewItem.Expanded">
    <BeginStoryboard Storyboard="{StaticResource ExpandStoryboard}" />
    </EventTrigger>
    <EventTrigger RoutedEvent="TreeViewItem.Collapsed">
    <BeginStoryboard Storyboard="{StaticResource CollapseStoryboard}" />
    </EventTrigger>
    Mittwoch, 10. März 2010 12:52
  • Hi Tristan,

    hmm. Warum willst Du unbedingt einen EventTrigger verwenden ..? Ich würde eher bei einem Style ansetzen. Etwas in der Art von:

    <Style TargetType="{x:Type TreeViewItem}">
       <Style.Resources>
          <Storyboard x:Key="ExpandStoryboard">
             <DoubleAnimation Storyboard.TargetProperty="Opacity"
                                             From="0"
                                             To="1" 
                                             Duration="0:0:0.3" />
             <DoubleAnimation Storyboard.TargetProperty="LayoutTransform.ScaleY" 
                                    FillBehavior="HoldEnd"
                                    From="0"
                                    To="1"
                                    Duration="0:0:0.3"/>
          </Storyboard>
          <Storyboard x:Key="CollapseStoryboard">
             <DoubleAnimation Storyboard.TargetProperty="Opacity"
                                    From="1"
                                    To="0" 
                                    Duration="0:0:0.3" />
             <DoubleAnimation Storyboard.TargetProperty="LayoutTransform.ScaleY" 
                                    FillBehavior="HoldEnd"
                                    From="1"
                                    To="0"
                                    Duration="0:0:0.3"/>
          </Storyboard>
       </Style.Resources>
       <Setter Property="LayoutTransform">
          <Setter.Value>
             <ScaleTransform/>
          </Setter.Value>
       </Setter>
       <Style.Triggers>
          <Trigger Property="IsVisible" Value="True">
             <Trigger.EnterActions>
                <StopStoryboard BeginStoryboardName="sbCollapse"/>
                <BeginStoryboard Storyboard="{StaticResource ExpandStoryboard}"
                                       x:Name="sbExpand"/>
             </Trigger.EnterActions>
             <Trigger.ExitActions>
                <StopStoryboard BeginStoryboardName="sbExpand"/>
                <BeginStoryboard Storyboard="{StaticResource CollapseStoryboard}"
                                       x:Name="sbCollapse"/>
             </Trigger.ExitActions>
          </Trigger>
       </Style.Triggers>
    </Style>
    

    Problem hierbei ist, dass das Storyboard beim Einklappen keine Chance hat, weil das ControlTemplate des TreeViews den ItemsPresenter (ItemsHost) auf <Visibility.Collapsed> setzt, wenn IsExpanded auf False gesetzt wird. Sprich, das wird wohl nur funktionieren, wenn Du das ControlTemplate letztlich vollständig überschreibst.

    Und BTW - als Benutzer fände ich es eher nervig, wenn ein Control, das wahrscheinlich permanent ein-/ausgeklappt wird, animiert wäre. :-)

    Und last but not least - habe gerade noch mal nachgeschaut, ob sich dazu was im Web finden lässt; ich finde aber lediglich einen Thread, der in die richtige Richtung geht: http://social.msdn.microsoft.com/Forums/en/wpf/thread/a5bb60ce-ddff-47ff-a4f0-44f1c0bb3a01 ...

    Ansonsten - poste halt mal etwas Lauffähiges . Den obigen Style habe ich einfach in die <Window.Resources>-Section meines Xml2TreeView Beispiels gepackt, damit kann man's wenigstens mal schnell ausprobieren.
    Cheers,
    Olaf
    http://blogs.intuidev.com
    Mittwoch, 10. März 2010 16:37
  • Hey Olaf,

    ja, mit Trigger Enter/Exit-Actions wird das zu realisieren sein; aber sollte ich mal wieder vor einem ähnlichen Problem stehen: hat der EventTrigger die Möglichkeit zu sagen, dass OriginalSource=TemplatedParent sein muss?

    Grüße,

    Tristan

    Donnerstag, 11. März 2010 11:18
  • Hi Tristan,

    ich verstehe leider absolut nicht, was Du damit meinen könntest ..?
    Cheers,
    Olaf
    http://blogs.intuidev.com
    Donnerstag, 11. März 2010 11:55
  • Hey Olaf,

    sorry, evtl. etwas schlech beschrieben. Der EventTrigger hat ja eine Eigenschaft "SourceName", sodass nur Events dieses Elements den Trigger auslösen können. Sinngemäß möchte ich SourceName="TemplatedParent" verwenden. Ist das irgendwie zu realisieren?
    Donnerstag, 11. März 2010 12:56
  • Hi Tristan,

    SourceName steht nur in Triggern zur Verfügung, die z.B. in einem ControlTemplate oder DataTemplate definiert wurden; dann bezieht es sich auf den Namen eines Controls, dass sich im Template befindet. Deswegen und weil ohnehin TemplatedParent eine Referenz (im Gegensatz zu einem Namen) wäre, macht Deine Aussage keinen (mir verständlichen) Sinn.

    Wenn du den Trigger auf ein best. Element innerhalb eines Templates ausführen möchtest, kannst Du den Namen verwenden - u.U. auch innerhalb eines MultiTriggers . Vielleicht machst Du dazu besser einen neuen Thread auf, in dem Du Dein Ansinnen näher erläuterst ..?
    Cheers,
    Olaf
    http://blogs.intuidev.com
    Donnerstag, 11. März 2010 13:41
  • Hey Olaf,

    dass "TemplatedParent" kein ElementName ist, ist mir klar - ich habe nur versucht zu erläutern welches Ziel ich verfolge.
    Ich möchte, dass der Trigger nur ausgelöst wird, wenn er vom "TemplatedParent" ausgelöst wird.

    Also nicht von einem Control innerhalb dieses Templates, sondern dem darzustellenden Controls selbst.

    Donnerstag, 11. März 2010 13:51
  • Hi Tristan,

    hmmm. Innerhalb eines DataTriggers könntest Du ein Binding verwenden, das wiederum auf TemplatedParent verweist. À la:

    <DataTemplate.Triggers>
       <DataTrigger Binding="{Binding Path=IsMouseOver, 
             RelativeSource={RelativeSource TemplatedParent}}" Value="True">
          <Setter TargetName="buttonsPanel" Property="Opacity" Value="1"></Setter>
       </DataTrigger>
       <DataTrigger Binding="{Binding Path=IsSelected, 
             RelativeSource={RelativeSource TemplatedParent}}" Value="True">
          <Setter TargetName="buttonsPanel" Property="Opacity" Value="1"></Setter>
       </DataTrigger>
    </DataTemplate.Triggers>
    

    Aber in einem EventTrigger - wüsste nicht, wie das gehen sollte.
    Cheers,
    Olaf
    http://blogs.intuidev.com
    Donnerstag, 11. März 2010 14:32
  • Hey Olaf,

    dann vermute ich, dass es wirklich technisch nicht möglich ist? Sollte ein Moderator hier mal drüber stolpern --> wäre ja evtl. eine Idee.
    Donnerstag, 11. März 2010 15:34
  • Hi Tristan,

    bin gerade per Zufall über die Reveal-Klasse in Kevin's Bag-o-Tricks gestolpert - wenn Du Expand/Collapse für die Nodes Deines TreeViews animieren willst, findest Du da einen Weg, der "vernünftig" funktioniert. Mir wär's den Aufwand nicht wert ... :-)
    Cheers,
    Olaf
    http://blogs.intuidev.com
    Samstag, 13. März 2010 11:13
  • Hallo Tristan,

    hasst Du eigentlich Dein Problem gelöst ? Wenn ja, es wäre schön, wenn Du posten würdest wie es funktioniert hat,
    denn dann profitieren unter Umständen andere mit dem gleichen Problem davon.

    Grüße,
    Robert

    Dienstag, 30. März 2010 11:21
    Moderator