Laden...

Command-Parameter Binding im Context-Menü

Letzter Beitrag vor einem Jahr 6 Posts 518 Views
Command-Parameter Binding im Context-Menü

Hallo!

Ich übergebe einem Command als Parameter eine Resource (die MainWindows-Resource).

Solang ich dieses Command außerhalb eines Context-Menüs aufrufe ist alles in Ordnung. Der Command-Parameter wird übergeben und das Command ausgeführt.

Sobald ich das Command aber innerhalb eines Context-Menüs ausführe:

<StatusBar.ContextMenu>
    <ContextMenu>
        <MenuItem Header="Nachrichten-Bereich anzeigen" Command="{Binding SBNachrichtenBereichAnzeigenCommand}" 
                    CommandParameter="{Binding Path=Resources, ElementName=wndMainWindow}"/>
    </ContextMenu>
</StatusBar.ContextMenu>

wird mir ein Bindungsfehler angezeigt:

MenuItem.CommandParameter:  Quelle nicht gefunden: ElementName=wndMainWindow

Dies hat seine Ursache in der Tatsache, dass das ContextMenu separate Fenster mit eigenem VisualTree und LogicalTree hat.

Eine vorgeschlagene Lösung ist, das CommandTarget manuell an das übergeordnete ContextMenu zu binden:

<StatusBar.ContextMenu>
    <ContextMenu>
        <MenuItem Header="Nachrichten-Bereich anzeigen" Command="{Binding SBNachrichtenBereichAnzeigenCommand}" 
                    CommandParameter="{Binding Path=Resources, ElementName=wndMainWindow}"
                    CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
    </ContextMenu>
</StatusBar.ContextMenu>

scheinbar hat das aber keine Auswirkung(en) auf den Command-Parameter. Der Bindungs-Fehler bleibt bestehen.

Wie könnte ich denn meinen Command-Parameter an die Resource(n) des MainWindow binden?

Hallo Th69!

Ich weiß jetzt zwar nicht, ob das alles so korrekt ist ... Ich habe einen MultiBinding Converter implementiert:

<StatusBar.ContextMenu>
    <ContextMenu>
        <MenuItem Header="Nachrichten-Bereich anzeigen" Command="{Binding SBNachrichtenBereichAnzeigenCommand}">
            <MenuItem.CommandParameter>
                <MultiBinding Converter="{StaticResource ResourcenKonverter}">
                    <Binding Path="Resources" ElementName="wndMainWindow" />
                    <Binding Path="." />
                </MultiBinding>
            </MenuItem.CommandParameter>
        </MenuItem>
    </ContextMenu>
</StatusBar.ContextMenu>

Der im Debugger auch "aufgerufen" wird, aber das Problem wird im Prinzip nur an die Stelle, wo ich das Einzelbindig auf die Resource binde verschoben.

MenuItem.CommandParameter: Object	Quelle nicht gefunden: ElementName=wndMainWindow	

Interessant: Das Einzelbinding (Path=".") verweist im Converter auf das View-Model (siehe Bild)

Binde ich den MultiConverter falsch?

Probiere mal, noch RelativeSource beim Binding zu setzen:

<Binding Path="Resources" ElementName="wndMainWindow" RelativeSource="{RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}" />

Hallo Th69!

Danke! für deinen Hinweis!

Das hatte ich schon am Anfang ... Ergibt den gleichen Fehler, deshalb habe ich es mit einem "festem" Namen probiert, dass erschien mir sicherer (um andere Fehler auszuschließen).

Ich habe jetzt erst einmal eine Lösung, die ist aber bestimmt tuning fähig!  😃

Innerhalb des CommandParameter-Bindings kann man auch ein PlacementTarget setzen!!!

<ContextMenu>
    <MenuItem Header="Nachrichten-Bereich anzeigen" 
                Command="{Binding SBNachrichtenBereichAnzeigenCommand}"
                CommandParameter="{Binding PlacementTarget, RelativeSource={
                RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"/>
</ContextMenu>

Dadurch erreicht man, dass der Command-Parameter einen Verweis auf die Status-Bar (welche sich wiederum ganz normal im VisualTree und LogicalTree befindet) zurückgibt.

Dadurch kann man mit Visual Tree Helpers die View und dadurch wieder die View-Resource(n) bestimmen.  Ziel erreicht.

private async void SBNachrichtenBereichAnzeigenExecuted(object obj)
{
    if(obj is System.Windows.Controls.Primitives.StatusBar sBar)                                    // StatusBar "holen"
    {                
        Window view = arWPF.WPF_Tools.WPF_Tools.VisualTreeHelpers.FindAncestor<Window>(sBar);       // View "holen"
        if (view != null && view.Resources is ResourceDictionary resourcen)                         // Resourcen "holen"
        {
            bool fertig = await VMDVDVerwaltung.SetDatenLadenBorder(resourcen, "Auf", 1000);        // Daten-Laden Border Animation ausführen
        }
    }
}

Nochmals vielen Dank  Th69 für deine Unterstützung!

Ich habe dich aber eher auf die falsche Fährte geführt.

Aber so habe ich auch etwas gelernt, denn das mit dem PlacementTarget wußte ich auch noch nicht. 😃