1

特定の状況でコマンドとしてイベントを実装する方法について少し混乱しています。MVVMを尊重したいのですが、この場合はどうすればよいかわかりません。

WPFの「ビュー」-viewCustomerSearchがあります。これにはいくつかのテキストボックスがあり、ユーザーが[検索]をクリックすると、結果がListViewに入力されます。viewCustomerSearchはviewmodelCustomerSearchにバインドされており、うまく機能します。

viewCustomerSearchはviewCustomerでホストされます。

viewCustomerSearchにカスタムコマンド(CustomerSelectedCommand)を公開させたいのですが、これはviesCustomerSearchのListViewがダブルクリックされるたびに「起動」され、viewCustomerの背後にあるviewmodel(viewmodelCustomer)によって処理されます。これは、理論上のMVVMパターンが正しく実装されているようです。

私は主な問題を3つの小さな問題に分解しましたが、うまくいけば、それらはすべて同じ課題の構成要素であることがわかります。

最初の問題:viewCustomerSearchにカスタムコマンドを公開させるには、このコードをviewCustomerSearchに配置する必要があるようです-これはMVVMを「壊す」ようです(ビューコードの後ろにコードがありません)。

public readonly DependencyProperty CustomerSelectedCommandProperty = DependencyProperty.Register("CustomerSelectedCommand", typeof(ICommand), typeof(viewCustomerSearch));

public ICommand CustomerSelectedCommand
{
    get { return (ICommand)GetValue(CustomerSelectedCommandProperty); }
    set { SetValue(CustomerSelectedCommandProperty, value); }
}

2番目の問題(そしてこれが本当に私に近づいている問題です):MVVMを壊す私が何をするかを示すことによって最もよく説明されます。ビューにイベントハンドラーがあります。

private void lstResults_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
    if (CustomerSelectedCommand != null) CustomerSelectedCommand.Execute(((ViewModels.viewmodelCustomerSearchResult)this.lstResults.SelectedItem).CustomerId);
}

ええと...このイベントハンドラーをここに置くべきではないことを私は知っています。むしろ、viewmodelCustomerSearchでそれを処理するコマンドが必要です。ここでの2つの問題は

  • 'CustomerSelectedCommand' ICommandはviewCustomerSearchに実装されているため、viewmodelCustomerSearchはそれを認識して起動することはできません。

  • ビューコードビハインドのイベントハンドラーではなく、MouseDoubleClickイベントをコマンドにバインドする方法がわかりません。添付プロパティについて読んでいますが、ここでどのように適用されるかわかりません。

(注意:アプリケーションの他の場所で一般的な「RelayCommand」を使用しています。これはここで機能しますか??)

3番目の問題:イベントハンドラーの背後にあるコードでコマンドを起動する非MVVMの方法を使用すると、選択された顧客IDを引数としてコマンドに渡していることがわかります。viewCustomerのコマンドハンドラーでその引数を確認するにはどうすればよいですか?それを処理するために新しいRelayCommandを作成しましたが、Executeメソッドは引数を取らないようですか?

上記のすべてを考えると、私は個人的に「MVVMはビューにコードがないことを意味します」を購読していないと言わなければなりません。それは私には気が狂っているようです。ビューに完全に関係し、ビューのみに関係するコードは、-IMHO-ビューモデルに含めるべきではありません。とはいえ、これは論理的なもののように見えます(ビューのものではありません)。

いくつかの洞察に感謝します。長い投稿でごめんなさい。あなたが「戦争と平和」で私を助けるのに十分な情報のバランスをとろうとしています。

DS

4

2 に答える 2

0

ビューで、xamlに「Command」プロパティを追加し、それをViewModelのコマンドにバインドできます。

Command="{Binding CustomerSelectedCommand}"

パラメータは複数の方法で渡すことができます。ほとんどの場合、ViewModelにバインドされている他のアイテムがあり、それらを直接使用できます。ただし、CommandParameterというプロパティもあります。これは、XAMLで指定する例です。

 CommandParameter="{Binding ElementName=txtPassword}"

次に、ViewModelでは、コマンドの定義は次のようになります。

private void UserLogonCommandExecute(object parameter)
{
...
       var password_box = parameter as PasswordBox;
...
}

ViewModelでRelayCommandを設定する方法をすでに知っているようですので、ここでは説明しません。開始時に、MVVMパターンを使用してデータ駆動型WPFアプリケーションを構築する方法が役立つことがわかりました。

コメントごとのリクエストコマンドプロパティの例

動作するコードをいくつか取得します。XAMLのボタンにCommandプロパティを追加する方法は次のとおりです。

<Button Command="{Binding ConnectCommand}">
//Your button content and closing </Button> here

これは、DataContextをConnectCommandというコマンドを持つViewModelに設定していることを前提としています。ConnectCommandの例を次に示します。ConnectCommandCanExecuteとConnectCommandExecuteの内容を、実行したい作業に置き換える必要があります。

public ICommand ConnectCommand
{
    get
    {
        if (_connectCommand == null)
        {
            _connectCommand = new RelayCommand(param => ConnectCommandExecute(),
                                               param => ConnectCommandCanExecute);
        }
        return _connectCommand;
    }
}

private bool ConnectCommandCanExecute
{
    get { return !_instrumentModel.IsConnected; }
}

private void ConnectCommandExecute()
{
    if (TcpSettingsChanged()) SaveTcpSettings();
    _instrumentModel.Connect(_tcpData);
}

RelayClass

これを単純にすることの一部は、コアライブラリ.dllの1つにあるRelayClassです。私はおそらく私が見たビデオの1つからこれを手に入れました。これは全体を切り取って貼り付けることができます。ここにある名前空間を変更したい場合を除いて、ここでカスタマイズする必要はありません。

using System;
using System.Diagnostics;
using System.Windows.Input;

namespace Syncor.MvvmLib
{
public class RelayCommand : ICommand
{
private readonly Action<object> _execute;
private readonly Predicate<object> _canExecute;

public event EventHandler CanExecuteChanged
{
  add
  {
    CommandManager.RequerySuggested += value;
  }
  remove
  {
    CommandManager.RequerySuggested -= value;
  }
}

public RelayCommand(Action<object> execute)
  : this(execute, (Predicate<object>) null)
{
  this._execute = execute;
}

public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
  if (execute == null)
    throw new ArgumentNullException("execute");
  this._execute = execute;
  this._canExecute = canExecute;
}

[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
  if (this._canExecute != null)
    return this._canExecute(parameter);
  else
    return true;
}

public void Execute(object parameter)
{
  this._execute(parameter);
}
}
}
于 2012-05-05T00:03:52.717 に答える
0

ビジネスロジックを制御できないように、「DoubleClickCommand」という名前を付けてみませんか。次に、Todが説明したように、このコマンドをビューモデルにバインドします。コードビハインドに関しては、純粋なxamlソリューションがあります。より正確には、アタッチされた動作が含まれますが、WPFクラス(回避したい)をオーバーライドする必要はありません。たとえば、「firecommandonevent」を検索してください。最後に、Code BehindはMVVMを壊すことはありません。この神話はどこから来たのだろうか、背後のコードは完全に問題ありません!MVVMは、ビューとロジックを分離するためのものであり、コードを配置する場所を指示するものではありません。設計の原則は、あなたを妨げるのではなく、助けるべきです。

于 2012-05-05T00:11:49.510 に答える