WPF: Menüelemente nur bind Befehlsparameter einmal
-
26-09-2019 - |
Frage
Ive dies ein paar Mal bemerkt, wenn sie mit Befehlen Menüs, sind sie nicht sehr dynamisch, überprüfen Sie diese aus. Ich bin ein Menü aus einer Sammlung von Farben zu schaffen, verwende ich es eine Spalte in einem Datagrid zu färben. Wie auch immer, wenn ich zum ersten Mal das Menü (es ist ein Kontextmenü) das Kommando Parameterbindung geschieht bringen und es bindet an die Säule, dass das Kontextmenü geöffnet wurde auf. Doch das nächste Mal, wenn ich es bringe es scheint wpf die Menü-Caches und es tut den Befehl Parameter erneut binden. so dass ich die Farbe nur auf der Anfangsspalte festlegen, dass das Kontextmenü erscheint auf.
Ich habe um diese Situation in der Vergangenheit bekam, indem sie das Menü vollständig dynamisch und zerstören die Sammlung, wenn das Menü geschlossen und zwingt eine das nächste Mal wieder aufzubauen geöffnet, ich dont wie dieser Hack. Hat jemand einen besseren Weg?
<MenuItem
Header="Colour"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ResultEditorGrid}}, Path=ColumnColourCollection}"
ItemTemplate="{StaticResource colourHeader}" >
<MenuItem.Icon>
<Image
Source="{StaticResource ColumnShowIcon16}" />
</MenuItem.Icon>
<MenuItem.ItemContainerStyle>
<Style
TargetType="MenuItem"
BasedOn="{StaticResource systemMenuItemStyle}">
<!--Warning dont change the order of the following two setters
otherwise the command parameter gets set after the command fires,
not mush use eh?-->
<Setter
Property="CommandParameter">
<Setter.Value>
<MultiBinding>
<MultiBinding.Converter>
<local:ColumnAndColourMultiConverter/>
</MultiBinding.Converter>
<Binding RelativeSource="{RelativeSource AncestorType={x:Type DataGridColumnHeader}}" Path="Column"/>
<Binding Path="."/>
</MultiBinding>
</Setter.Value>
</Setter>
<Setter
Property="Command"
Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:ResultEditorGrid}}, Path=ColourColumnCommand}" />
</Style>
</MenuItem.ItemContainerStyle>
</MenuItem>
Lösung
Das Problem ist, dass ContextMenu die sind offenbar die Wurzel ihrer eigenen visuellen Struktur ich irgendwo gelesen, dass es die Datacontext nimmt seinen Eltern, aber nur einmal beim Laden, so dass, wenn die Eltern die Datacontext menuitems ändert sich nicht. (Leider kann ich keinen Link für das finden Recht nicht)
Ich habe dieses Problem vor, und was ich tat, war die Verwendung Virtual Zweig Muster Josh Smith. Es ist ziemlich technisch, aber der Artikel hat mir geholfen wirklich gut verstehen, was mit diesem visuellen Baum Unsinn vorging.
Im Wesentlichen erstellen Sie diese Brücke, dass bindet an die Datacontext Sicht. Die Brücke wird erstellt als statische Ressource , so dass Sie es aus dem Kontextmenü zu binden, auch wenn sie außerhalb der visuellen Struktur ist.
Fügen Sie diese auf Ihre XAML:
<Window.Resources>
<!-- This is the "root node" in the virtual branch
attached to the logical tree. It has its
DataContext set by the Binding applied to the
Window's DataContext property. -->
<FrameworkElement x:Key="DataContextBridge" />
</Window.Resources>
<Window.DataContext>
<!-- This Binding sets the DataContext on the "root node"
of the virtual logical tree branch. This Binding
must be applied to the DataContext of the element
which is actually assigned the data context value. -->
<Binding
Mode="OneWayToSource"
Path="DataContext"
Source="{StaticResource DataContextBridge}"
/>
</Window.DataContext>
Dies ist die Brücke, die ich gesprochen hat. Es nimmt die Datacontext und __pushes it_ bis zu den Brücken Datacontext, die (wie gesagt) eine statische Ressource.
Sie dann einfach diese auf die contextmenu Datacontext:
DataContext="{Binding
Source={StaticResource DataContextBridge},
Path=DataContext}"
werfen nun alle relativ Wegfindung usw. entfernt und regelmäßige Verwendung innerhalb der Menüpunkte zu binden, und Sie sollten in Ordnung sein. Die Datacontext wird wie gewohnt aktualisieren.
Nur eine Anmerkung:
Sie werden natürlich eine Eigenschaft in der Datacontext haben müssen, zu erkennen, welchen Befehl zu verwenden, aber ich bin sicher, können Sie es herausfinden. Diese Lösung nur befasst sich mit dem Update tun sie nicht die Art und Weise contextmenu