myCSharp.de - DIE C# und .NET Community
Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 
 | Suche | FAQ

» Hauptmenü
myCSharp.de
» Startseite
» Forum
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Suche
» Regeln
» Wie poste ich richtig?
» Forum-FAQ

Mitglieder
» Liste / Suche
» Wer ist wo online?

Ressourcen
» openbook: Visual C#
» openbook: OO
» Microsoft Docs

Team
» Kontakt
» Übersicht
» Wir über uns

» myCSharp.de Diskussionsforum
Du befindest Dich hier: Community-Index » Diskussionsforum » Entwicklung » GUI: WPF und XAML » Wie bekomme ich ein korrektes CommandParameter Binding mit dynamischem Menüs in Wpf und Xaml
Letzter Beitrag | Erster ungelesener Beitrag Druckvorschau | Thema zu Favoriten hinzufügen

Antwort erstellen
Zum Ende der Seite springen  

Wie bekomme ich ein korrektes CommandParameter Binding mit dynamischem Menüs in Wpf und Xaml

 
Autor
Beitrag « Vorheriges Thema | Nächstes Thema »
return01 return01 ist männlich
myCSharp.de-Mitglied

Dabei seit: 29.10.2017
Beiträge: 5
Entwicklungsumgebung: Visual Studio 2010


return01 ist offline

Wie bekomme ich ein korrektes CommandParameter Binding mit dynamischem Menüs in Wpf und Xaml

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,
ich habe ein dynamischen Menü Service in meiner WPF Applikation. Dabei soll jedes Command
verschiedene CommandParameter bekommen können.


Das Problem:
Wenn ich mit meiner Lösung die CommandParameter in Xaml setze, wird die CanExecute Property
nicht mehr ausgewertet.

Was ich soweit programmiert habe:

Ich benutze mvvm-light und fody-propertychanged.

Hier die Menü Klasse:

C#-Code:
    public class MyMenu : INotifyPropertyChanged
    {
        private ObservableCollection<MyMenu> myChildren;

        public MyMenu()
        {
            myChildren = new ObservableCollection<MyMenu>();
        }
        public string Header { get; set; }
        public string Image { get; set; }
        public string CommandName { get; set; } //used to set the CommandParameter binding
        public ICommand Command { get; set; }
        public ObservableCollection<MyMenu> Children {
            get
            {
                return myChildren;
            }
            private set
            {
                myChildren = value;
            }
        }


        public event PropertyChangedEventHandler PropertyChanged;
    }

Diese Klasse wird vom Menü Service benutzt:

C#-Code:
    public sealed class MenuService : INotifyPropertyChanged
    {
        private static readonly Lazy<MenuService> lazy = new Lazy<MenuService>(() => new MenuService());

        public static MenuService Instance { get { return lazy.Value; } }

        private ObservableCollection<MyMenu> myMainMenu;

        public event PropertyChangedEventHandler PropertyChanged;

        private MenuService()
        {
            myMainMenu = new ObservableCollection<MyMenu>();
        }

        public ObservableCollection<MyMenu> MainMenu
        {
            get
            {
                return myMainMenu;
            }
            private set
            {
                myMainMenu = value;
            }
        }
    }

Im Konstruktor vom Viewmodel hole ich mir die Instanz vom Menüservice und füge ein paar Menüpunkte hinzu:

C#-Code:
    private void AddMenuItems()
    {
        MyMenu OpenUserLoginMenuItem = new MyMenu
        {
            Header = "_Login",
            Image = "./Icons/IconLogin.png",
            Command = OpenSelectTestprocedureWindowCommand,
            CommandName = "OpenUserLoginDialogCommand"
        };

        MyMenu OpenSelectTestprocedureMenuItem = new MyMenu
        {
            Header = "_Select Testprocedure",
            Image = "./Icons/IconSelectTestprocedure.png",
            Command = OpenSelectTestprocedureWindowCommand,
            CommandName = "OpenSelectTestprocedureWindowCommand"
        };

        MainMenu.Add(OpenUserLoginMenuItem);
        MainMenu.Add(OpenSelectTestprocedureMenuItem);
    }

Im Viewmodel habe ich die bindable property:

C#-Code:
    public ObservableCollection<MyMenu> MainMenu
    {
        get
        {
            return myMenuService.MainMenu;
        }
    }

Hier die Kommandos als RelayCommand:

C#-Code:
    //in the constructor
    OpenSelectTestprocedureWindowCommand = new RelayCommand<ShowTestschrittViewParameter>(OpenSelectTestablaufWindow, CanOpenSelectTestablaufWindow);
    OpenUserLoginDialogCommand = new RelayCommand<Type>(OpenUserLoginDialog);

    private void OpenUserLoginDialog(Type aWindowType)
    {
        myNavigationService.ShowWindowModal(aWindowType);
    }

    private bool CanOpenSelectTestablaufWindow(ShowTestschrittViewParameter showTestschrittViewParameter)
    {
        if (myDataService.CurrentTestProcedure != null)
        {
            if (myDataService.CurrentTestProcedure.TestProcedureState == Logic.Model.GlobalTypes.TestProcedureState.Running) return false;
        }
        return new ViewModelLocator().UserLoginDialogViewModel.User.NameIsValid;
    }

    private void OpenSelectTestablaufWindow(ShowTestschrittViewParameter showTestschrittViewParameter)
    {
        myNavigationService.ShowTestschrittView(showTestschrittViewParameter);
    }

Und im MainView habe ich das folgende xaml:

XML-Code:
    <Menu Grid.Row="2" ItemsSource="{Binding MainMenu}" Name="DynamicMenu">
        <!--<Menu.ItemTemplate>
            <DataTemplate DataType="{x:Type luih:MyMenu}">
                <StackPanel>
                        <Label Content="{Binding Header}"/>
                        <Image Source="{Binding Image}"/>
                    </StackPanel>
            </DataTemplate>
        </Menu.ItemTemplate>-->

        <Menu.ItemContainerStyle>
            <Style TargetType="{x:Type MenuItem}">
                <Setter Property="Header" Value="{Binding Header}"/>
                <Setter Property="Command" Value="{Binding Command}"/>
                <Setter Property="ItemsSource" Value="{Binding Children}"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding CommandName}" Value="OpenUserLoginDialogCommand">
                        <Setter Property="CommandParameter" Value="{x:Type local:UserLoginDialog}"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding CommandName}" Value="OpenSelectTestprocedureWindowCommand">
                        <Setter Property="CommandParameter" Value="{x:Type local:UserLoginDialog}"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </Menu.ItemContainerStyle>
    </Menu>

Achtung. Der CommandParameter type im Binding ist noch nicht korrekt. Diese Problem wollte ich später lösen. Aber zum testen sollte es reichen. Es gibt mir halt eine Ausnahme, weil der Parameter vom falschen Typ ist.


Wenn ich die CommandParameter im Style.Trigger mit dem DataTrigger setze, wird die CanExecute Property nicht mehr ausgewertet. Das entsprechende MenüItem bleibt grau.

Wenn ich diesen Teil im xaml auskommentiere, funktioniert alles wie erwartet. Aber dann fehlen mir die Parameter.

Jeder Tipp in die richtige Richtung ist willkommen.
Neuer Beitrag 08.02.2020 09:47 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
return01 return01 ist männlich
myCSharp.de-Mitglied

Dabei seit: 29.10.2017
Beiträge: 5
Entwicklungsumgebung: Visual Studio 2010

Themenstarter Thema begonnen von return01

return01 ist offline

Beitrag: beantworten | zitieren | editieren | melden/löschen       | Top

Hallo,

ich habe die Lösung gefunden. Das Problem war hausgemacht:

RelayCommand aus mvvm light wertet den Typ aus mit dem die CanExecute Funktion aufgerufen wird.
Ist dieser vom falschen Typ oder nicht null, wird diese Funktion nicht aufgerufen.

Die Lösung zum Testen, ohne den korrekten Typ zu übergeben, wäre gewesen:

XML-Code:
<Style TargetType="{x:Type MenuItem}">
    <Setter Property="CommandParameter" Value="{x:Null}"/>
</Style>
Neuer Beitrag 09.02.2020 07:56 E-Mail | Beiträge des Benutzers | zu Buddylist hinzufügen
Baumstruktur | Brettstruktur       | Top 
myCSharp.de | Forum Der Startbeitrag ist älter als 3 Monate.
Der letzte Beitrag ist älter als 3 Monate.
Antwort erstellen


© Copyright 2003-2020 myCSharp.de-Team | Impressum | Datenschutz | Alle Rechte vorbehalten. | Dieses Portal verwendet zum korrekten Betrieb Cookies. 29.05.2020 14:21