我如何通过wpf和mvvm中的动态菜单获取正确的CommandParameter绑定

问题描述 投票:0回答:1

我在WPF应用程序中实现了动态菜单服务。每个命令可以或应该具有不同的CommandParameter。

问题:通过在xaml中设置CommandParamter绑定的解决方案,命令中的CanExecute属性不再更新。

[到目前为止我有什么

我正在使用mvvm-light和fody-propertychanged。

这里是菜单类别:

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

此类由MenuService使用:

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

在viewmodel的构造函数中,我获得MenuService的实例并添加一些项目:

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

然后我在viewmodel中具有可绑定的属性:

public ObservableCollection<MyMenu> MainMenu
{
    get
    {
        return myMenuService.MainMenu;
    }
}

这里命令实现为RelayCommand:

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

然后在MainView中,我具有以下xaml:

<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>

注意。 xaml中的CommandParameter绑定类型当前不正确。这是另一个问题,我会自己解决。但是出于测试目的,它应该可以工作。由于类型错误,它将给我一个例外。

但是当我使用DataTrigger在Style.Trigger中进行CommandParameter绑定时,CanExecute属性确实在运行时更新了。当我对本节进行评论时,一切正常。但后来我没有CommandParameters。

欢迎任何帮助和建议。

wpf menu mvvm-light fody-propertychanged wvvm
1个回答
0
投票

我发现了问题。

来自mvvm指示灯的RelayCommand评估CanExecute函数的参数类型。这必须是正确的声明类型或null。

因此,出于测试目的,我必须像这样设置绑定:

 <Style TargetType="{x:Type MenuItem}">
    <Setter Property="CommandParameter" Value="{x:Null}"/>
</Style>
© www.soinside.com 2019 - 2024. All rights reserved.