1

私はしばらくWPFを使用していますが、コマンドは初めてですが、一度適切に使用したいと考えています。コード例に従って、すべてのコマンドを保持する別の静的 Commands クラスを確立しました。これは次のようになります。

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 の Button コントロールにバインドされることですが、OpenDocument_CanExecute メソッドは MainWindow.xaml の DataGrid を調べて、項目が選択されているかどうかを確認する必要があることです。

メソッドが DataGrid を認識できるようにするにはどうすればよいですか?

解決

Ken の返信 (ありがとうございます!) に触発されて、次のように配置しました。これは完全に機能します。

MainWindow.xaml.cs

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

        Loaded += delegate
        {
            DataContext = ViewModel.Current;
            Commands.BindCommands(this);
        };
    }
}

ViewModel.cs

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

Commands.cs

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

    }
}
4

3 に答える 3

3

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

明らかに、私はたくさんのものを省きました。しかし、このパターンは過去に私にとってうまく機能しました。

于 2012-04-26T19:22:42.777 に答える
0

コマンドをUI実装と緊密に結合しているのに、なぜコマンドを実装するのでしょうか。datagrid.SelectionChangedに応答し、何が起こるかをコーディングするだけです。

それ以外の場合は、ViewModelに配置します。ViewModelにその状態を監視させ、CanExeがtrueであるかどうかを評価します。

編集

一方、Exe()メソッドとCanExe()メソッドだけでなく、コマンドにパラメーターを渡すこともできます。

//where T is the type you want to operate on
public static RoutedUICommand<T> OpenDocument { get; set; }
于 2012-04-26T17:51:00.900 に答える
0

MVVM ソリューションを実行している場合は、コントロールが相互に「対話」できるパブリッシュ/サブスクライブ アグリゲーターを実装するのに最適な時期です。その背後にある要点は、データグリッドがイベント「ドキュメントを開く」を発行することです。後続のコントロールは、イベントをサブスクライブし、'Open Document' の呼び出しに反応する可能性があります。パブリッシュ/サブスクライブ パターンは、データグリッドとコントロールの緊密な結合を防ぎます。イベント アグリゲーターを検索してみてください。

于 2012-04-26T19:21:58.993 に答える