如何在视图模型中的视图上使用路由命令

发布于 2024-12-10 04:05:03 字数 1072 浏览 0 评论 0原文

我试图在我的视图上使用 RoutedCommand,以便我可以使用 CanExecute 功能,但我可以让它工作的唯一方法是使用 Prism 中的 DelegateCommand。当我尝试使用 RoutedCommand 时,按钮保持不活动状态,并且 CanExecute 函数永远不会被使用。

我尝试在 XAML 上放置 CommandBinding,但这给出了“只有生成的或代码隐藏类上的实例方法才有效”。错误。这是该代码:

<Window.CommandBindings>
    <CommandBinding Command="AddCommand"
                Executed="my:SettingsDialogViewModel.AddCommandMethod"
                CanExecute="my:SettingsDialogViewModel.AddCommandMethodCanExecute" />
</Window.CommandBindings>

我还尝试在代码中设置 CommandBinding,但这也没有帮助。我只是不确定如何让它工作,缺少将其粘贴在代码隐藏中,或者实现一些我在网上找到的看起来极其复杂的东西。

感谢您的帮助:)

编辑: 以下是我尝试使用的方法:

public void AddCommandMethod()
{
    if (SelectedMain != null)
    {
        SelectedMain.IsDirty = true;
        _faveAppList.Add(SelectedMain);
        SelectedMain.ListOrder = _faveAppList.Count;
        _mainAppList.Remove(SelectedMain);
        _listDirty = true;
    }
}
public void AddCommandMethodCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}

I am trying to use a RoutedCommand on my view so that I can use the CanExecute functionality, but the only way I can get it to work is with a DelegateCommand from Prism. When I try to use the RoutedCommand the button stays inactive and the CanExecute function never gets used.

I've tried putting a CommandBinding on my XAML but that gives a "Only instance methods on the generated or code-behind class are valid." error. Here is that code:

<Window.CommandBindings>
    <CommandBinding Command="AddCommand"
                Executed="my:SettingsDialogViewModel.AddCommandMethod"
                CanExecute="my:SettingsDialogViewModel.AddCommandMethodCanExecute" />
</Window.CommandBindings>

I've also tried setting up a CommandBinding in code, but that doesn't help either. I'm just not sure how to get it to work, short of sticking it in the code-behind, or implementing some ridiculously complicated looking thing I've found on the web.

Thanks for any help :)

EDIT:
Here are the methods I am trying to use:

public void AddCommandMethod()
{
    if (SelectedMain != null)
    {
        SelectedMain.IsDirty = true;
        _faveAppList.Add(SelectedMain);
        SelectedMain.ListOrder = _faveAppList.Count;
        _mainAppList.Remove(SelectedMain);
        _listDirty = true;
    }
}
public void AddCommandMethodCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

时光清浅 2024-12-17 04:05:03

这不是正确的 MVVM 表示法。我将提供一种方法来做到这一点。

// MyView.cs
public class MyView : UserControl
{ 
    public MyViewViewModel ViewModel 
    { 
        get { return (MyViewViewModel) DataContext;}
        set { DataContext = value; }
    }
}

// DelegateCommand.cs
public class DelegateCommand : ICommand
{
      private readonly Predicate<object> _canExecute;
      private readonly Action<object> _execute;

      public DelegateCommand(Action<object> execute)
           : this(execute, null) {}

      public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
      {
           _execute = execute;
           _canExecute = canExecute;
      }

      public override bool CanExecute(object parameter)
      {
          if (_canExecute == null)
          {
            return true;
          }
          return _canExecute(parameter);
      }

      public override void Execute(object parameter)
      {
        _execute(parameter);
      }     
 }

 // MyViewViewModel.cs
 public class MyViewViewModel 
 {
    public ICommand AddCommand {get;set;}

    public MyViewViewModel()
    {
          AddCommand = new DelegateCommand (AddCommandMethod, AddCommandMethodCanExecute);
    }

    private void AddCommandMethod (object parameter)
    {

    }

    private bool AddCommandMethodCanExecute(object parameter)
    {
         // Logic here
         return true;
    }
 }

 // MyView.xaml

 <Button Command="{Binding AddCommand}" />

That isn't the proper MVVM notation. I'll provide one way of doing this.

// MyView.cs
public class MyView : UserControl
{ 
    public MyViewViewModel ViewModel 
    { 
        get { return (MyViewViewModel) DataContext;}
        set { DataContext = value; }
    }
}

// DelegateCommand.cs
public class DelegateCommand : ICommand
{
      private readonly Predicate<object> _canExecute;
      private readonly Action<object> _execute;

      public DelegateCommand(Action<object> execute)
           : this(execute, null) {}

      public DelegateCommand(Action<object> execute, Predicate<object> canExecute)
      {
           _execute = execute;
           _canExecute = canExecute;
      }

      public override bool CanExecute(object parameter)
      {
          if (_canExecute == null)
          {
            return true;
          }
          return _canExecute(parameter);
      }

      public override void Execute(object parameter)
      {
        _execute(parameter);
      }     
 }

 // MyViewViewModel.cs
 public class MyViewViewModel 
 {
    public ICommand AddCommand {get;set;}

    public MyViewViewModel()
    {
          AddCommand = new DelegateCommand (AddCommandMethod, AddCommandMethodCanExecute);
    }

    private void AddCommandMethod (object parameter)
    {

    }

    private bool AddCommandMethodCanExecute(object parameter)
    {
         // Logic here
         return true;
    }
 }

 // MyView.xaml

 <Button Command="{Binding AddCommand}" />
分开我的手 2024-12-17 04:05:03

更好的选择是实现 ICommand< /code>接口并在实现的方法中编写逻辑。然后你的视图模型可以返回你的自定义命令,你可以从你的视图绑定到它。

这会将实际的命令实现与视图模型分开,但您仍然可以在视图模型中很好地实现逻辑。

像这样的事情:

public abstract class BaseCommand : ICommand
{
    // needed to connect to WPF's commanding system
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public abstract bool CanExecute(object parameter);
    public abstract void Execute(object parameter);
}

public class AddCommand : BaseCommand
{
    private readonly MyViewModel _vm;
    public AddCommand(MyViewModel vm)
    {
        this._vm = vm;
    }
    public override bool CanExecute(object parameter)
    {
        // delegate back to your view model
        return _vm.CanExecuteAddCommand(parameter);
    }
    public override void Execute(object parameter)
    {
        _vm.ExecuteAddCommand(parameter);
    }
}

public class MyViewModel
{
    public ICommand AddCommand { get; private set; }
    public MyViewModel()
    {
        AddCommand = new AddCommand(this);
    }

    public bool CanExecuteAddCommand(object parameter)
    {
    }

    public void ExecuteAddCommand(object parameter)
    {
    }
}

然后只需绑定发出命令的控件即可。

<Button Command="{Binding AddCommand}">...</Button>

A better option would be to implement the ICommand interface and write your logic in the implemented methods. Then your view model can return your custom command and you could just bind to it from your view.

This will separate the actual command implementation from your view model but you can still nicely implement the logic within your view model.

Something like this:

public abstract class BaseCommand : ICommand
{
    // needed to connect to WPF's commanding system
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public abstract bool CanExecute(object parameter);
    public abstract void Execute(object parameter);
}

public class AddCommand : BaseCommand
{
    private readonly MyViewModel _vm;
    public AddCommand(MyViewModel vm)
    {
        this._vm = vm;
    }
    public override bool CanExecute(object parameter)
    {
        // delegate back to your view model
        return _vm.CanExecuteAddCommand(parameter);
    }
    public override void Execute(object parameter)
    {
        _vm.ExecuteAddCommand(parameter);
    }
}

public class MyViewModel
{
    public ICommand AddCommand { get; private set; }
    public MyViewModel()
    {
        AddCommand = new AddCommand(this);
    }

    public bool CanExecuteAddCommand(object parameter)
    {
    }

    public void ExecuteAddCommand(object parameter)
    {
    }
}

Then just bind controls that issues the command.

<Button Command="{Binding AddCommand}">...</Button>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文