C# 在WPF中,命令';s CanExecute方法是否可以获得其他UI元素的可见性?

C# 在WPF中,命令';s CanExecute方法是否可以获得其他UI元素的可见性?,c#,wpf,command,C#,Wpf,Command,我已经使用WPF有一段时间了,但我对命令还不熟悉,但我想开始正确地使用它们一次。下面是一个代码示例,我建立了一个单独的staticcommands类来保存我的所有命令,如下所示 public static class Commands { public static RoutedUICommand OpenDocument { get; set; } static Commands() { OpenDocument = new RoutedUIComma

我已经使用WPF有一段时间了,但我对命令还不熟悉,但我想开始正确地使用它们一次。下面是一个代码示例,我建立了一个单独的staticcommands类来保存我的所有命令,如下所示

public static class Commands
{
    public static RoutedUICommand OpenDocument { get; set; }

    static Commands()
    {
        OpenDocument = new RoutedUICommand("Open Document", "OpenDocument", typeof(Commands));
    }

    public static void BindCommands(Window window)
    {
        window.CommandBindings.Add(new CommandBinding(OpenDocument, OpenDocument_Executed, OpenDocument_CanExecute));
    }

    private static void OpenDocument_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        // Should be set to true if an item is selected in the datagrid.
    }

    private static void OpenDocument_Executed(object sender, ExecutedRoutedEventArgs e)
    {

    }
}
我的问题是,尽管命令将绑定到MainWindow.xaml中的按钮控件,但OpenDocument_CanExecute方法需要查看MainWindow.xaml中的数据网格,以查看是否选择了某个项

我如何将事情连接起来,使方法可以看到DataGrid

解决方案

受Ken回复的启发(再次感谢!),我将以下内容放在适当的位置,效果非常好

MainWindow.xaml.cs

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();

        Loaded += delegate
        {
            DataContext = ViewModel.Current;
            Commands.BindCommands(this);
        };
    }
}
public class ViewModel
{
    private static ViewModel _current;
    public static ViewModel Current
    {
        get { return _current ?? (_current = new ViewModel()); }
        set { _current = value; }
    }

    public object SelectedItem { get; set; }
}
public static class Commands
{
    public static RoutedUICommand OpenDocument { get; set; }

    static Commands()
    {
        OpenDocument = new RoutedUICommand("Open Document", "OpenDocument", typeof(Commands));
    }

    public static void BindCommands(Window window)
    {
        window.CommandBindings.Add(new CommandBinding(OpenDocument, OpenDocument_Executed, OpenDocument_CanExecute));
    }

    private static void OpenDocument_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = ViewModel.Current.SelectedItem != null;
    }

    private static void OpenDocument_Executed(object sender, ExecutedRoutedEventArgs e)
    {

    }
}
ViewModel.cs

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();

        Loaded += delegate
        {
            DataContext = ViewModel.Current;
            Commands.BindCommands(this);
        };
    }
}
public class ViewModel
{
    private static ViewModel _current;
    public static ViewModel Current
    {
        get { return _current ?? (_current = new ViewModel()); }
        set { _current = value; }
    }

    public object SelectedItem { get; set; }
}
public static class Commands
{
    public static RoutedUICommand OpenDocument { get; set; }

    static Commands()
    {
        OpenDocument = new RoutedUICommand("Open Document", "OpenDocument", typeof(Commands));
    }

    public static void BindCommands(Window window)
    {
        window.CommandBindings.Add(new CommandBinding(OpenDocument, OpenDocument_Executed, OpenDocument_CanExecute));
    }

    private static void OpenDocument_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = ViewModel.Current.SelectedItem != null;
    }

    private static void OpenDocument_Executed(object sender, ExecutedRoutedEventArgs e)
    {

    }
}
命令.cs

public partial class MainWindow
{
    public MainWindow()
    {
        InitializeComponent();

        Loaded += delegate
        {
            DataContext = ViewModel.Current;
            Commands.BindCommands(this);
        };
    }
}
public class ViewModel
{
    private static ViewModel _current;
    public static ViewModel Current
    {
        get { return _current ?? (_current = new ViewModel()); }
        set { _current = value; }
    }

    public object SelectedItem { get; set; }
}
public static class Commands
{
    public static RoutedUICommand OpenDocument { get; set; }

    static Commands()
    {
        OpenDocument = new RoutedUICommand("Open Document", "OpenDocument", typeof(Commands));
    }

    public static void BindCommands(Window window)
    {
        window.CommandBindings.Add(new CommandBinding(OpenDocument, OpenDocument_Executed, OpenDocument_CanExecute));
    }

    private static void OpenDocument_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = ViewModel.Current.SelectedItem != null;
    }

    private static void OpenDocument_Executed(object sender, ExecutedRoutedEventArgs e)
    {

    }
}

如果您将命令与UI实现紧密耦合,为什么还要实现命令呢?只需响应datagrid.SelectionChanged并编写应该发生的事情

否则,请将其放在ViewModel中。让ViewModel监视其状态,并在CanExe为真时进行评估

编辑

另一方面,可以向命令以及Exe()和CanExe()方法传递参数

//其中T是要操作的类型
公共静态RoutedUICommand和OpenDocument{get;set;}

如果您正在开发MVVM解决方案,这将是实现发布/订阅聚合器的最佳时机,该聚合器允许控件相互“对话”。背后的要点是datagrid将发布一个事件“Open Document”。后续控件可以订阅事件并对调用“打开文档”作出响应。发布/订阅模式防止数据网格和控件紧密耦合。搜索一些事件聚合器,我想你就可以开始了。

ICommand
实现在MVVM模式下工作得最好:

class ViewModel : INotifyPropertyChanged {
    class OpenDocumentCommand : ICommand {
        public bool CanExecute(object parameter) {
            return ViewModel.ItemIsSelected;
        }
        public OpenDocumentCommand(ViewModel viewModel) {
            viewModel.PropertyChanged += (s, e) => {
                if ("ItemIsSelected" == e.PropertyName) {
                    RaiseCanExecuteChanged();
                }
            };
        }
    }

    private bool _ItemIsSelected;

    public bool ItemIsSelected {
        get { return _ItemIsSelected; }
        set {
            if (value == _ItemIsSelected) return;
            _ItemIsSelected = value;
            RaisePropertyChanged("ItemIsSelected");
        }
    }

    public ICommand OpenDocument { 
        get { return new OpenDocumentCommand(this); } 
    }
}

显然,我漏掉了一大堆东西。但这种模式在过去对我很有效。

哦,我明白了。所以本质上,我只需要将我的UI绑定到一个模型对象,然后在绑定该对象时将该模型传递到我的commands类中?非常好。我做了一些稍微不同的事情(稍后我会发布),但本质上是一样的。谢谢你的帮助!