ViewModelからコマンドへのパラメーターとして変数を送信しようとしています。コマンドは次のようになります。
public class EditPersonCommand : ICommand
{
private bool _CanExecute = false;
public bool CanExecute(object parameter)
{
PersonModel p = parameter as PersonModel;
CanExecuteProperty = (p != null) && (p.Age > 0);
return CanExecuteProperty;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter) { }
private bool CanExecuteProperty
{
get { return _CanExecute; }
set
{
if (_CanExecute != value)
{
_CanExecute = value;
EventHandler can_execute = CanExecuteChanged;
if (can_execute != null)
{
can_execute.Invoke(this, EventArgs.Empty);
}
}
}
}
}
ViewModelは次のようになります。
public class PersonViewModel : ViewModelBase
{
private PersonModel _PersonModel;
private EditPersonCommand _EditPersonCommand;
///<remarks>
/// must use the parameterless constructor to satisfy <Window.Resources>
///</remarks>
public PersonViewModel()
: this(new PersonModel())
{
}
public PersonViewModel(PersonModel personModel)
{
_PersonModel = personModel;
}
public ICommand EditPersonCommand
{
get
{
if (_EditPersonCommand == null)
{
_EditPersonCommand = new EditPersonCommand();
}
return _EditPersonCommand;
}
}
}
Xamlは次のようになります。
<Button Content="Edit" HorizontalAlignment="Right" Height="20" Width="80"
Command="{Binding EditPersonCommand}"
CommandParameter="{Binding _PersonModel}" />
プライベートローカル変数名を使用する代わりに、ViewModelでプロパティを作成しようとしましたが、それも機能しませんでした。 object parameter
はnull
の呼び出しで常にCanExecute
を表示し、ボタンが有効になることはありません。 CommandParameter
の値をHello
に変更すると、Hello
の呼び出しでCanExecute
を受け取るので、変数が機能しない理由がわかりません。 。どんな助けでもいただければ幸いです。
更新:モデルにパブリックプロパティを作成しようとしました(モデルを公開したくありませんが、機能するかどうかを確認するために試しましたが、機能しません)。
// Added this to the ViewModel
public PersonModel PersonModelProp
{
get
{
return _PersonModel;
}
set
{
_PersonModel = value;
OnPropertyChanged("PersonModelProp");
}
}
そして、xamlをこれに変更しました:
<Button Content="Edit" HorizontalAlignment="Right" Height="20" Width="80"
Command="{Binding EditPersonCommand}"
CommandParameter="{Binding PersonModelProp}" />
しかし、それでも運はありません。 ViewModelはINotifyPropertyChanged
を実装します
CommandParameterは常にnullですか、それとも最初に実行されたときにのみチェックしますか?
この場合、Commandプロパティを設定すると、CommandParameterが設定される直前にCanExecuteが起動するため、プロパティを宣言する順序が重要であるように見えます。
Commandプロパティの前にCommandParameterプロパティを移動してみてください。
<Button Content="Edit" HorizontalAlignment="Right" Height="20" Width="80"
CommandParameter="{Binding PersonModelProp}"
Command="{Binding EditPersonCommand}" />
編集
イベントが適切に発生していることを確認するには、PersonModelProp
値が変更されたときにCanExecuteChangedイベントを発生させる必要があります。
コマンド:
public class EditPersonCommand : ICommand
{
public bool CanExecute(object parameter)
{
PersonModel p = parameter as PersonModel;
return p != null && p.Age > 0;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
//command implementation
}
public void RaiseCanExecuteChanged()
{
var handler = CanExecuteChanged;
if(handler != null)
{
handler(this, EventArgs.Empty);
}
}
}
そしてビューモデル:
public class PersonViewModel : ViewModelBase
{
private PersonModel _PersonModel;
private EditPersonCommand _EditPersonCommand;
///<remarks>
/// must use the parameterless constructor to satisfy <Window.Resources>
///</remarks>
public PersonViewModel()
: this(new PersonModel())
{
_EditPersonCommand = new EditPersonCommand();
}
public PersonViewModel(PersonModel personModel)
{
_PersonModel = personModel;
}
public ICommand EditPersonCommand
{
get
{
return _EditPersonCommand;
}
}
public PersonModel PersonModelProp
{
get
{
return _PersonModel;
}
set
{
_PersonModel = value;
OnPropertyChanged("PersonModelProp");
EditPersonCommand.RaiseCanExecuteChanged();
}
}
}
答えへの2つのポイント:
まず、@ aktonが述べたように、バインドできるのはpublic propertiesのみです。 する必要はありませんDependencyPropertyですが。
次に、理解するのに少し時間がかかりましたが、CommandParameterbeforeのバインディングを設定する必要があるということです- コマンドプロパティ。つまり.
<Button Content="Edit" HorizontalAlignment="Right" Height="20" Width="80"
CommandParameter="{Binding PersonModelProp}"
Command="{Binding EditPersonCommand}" />
お役に立てれば :)
_PersonModel
はプライベートであるため、アクセスできません。それを公開するパブリックプロパティを作成し、CommandParameter
でそれにバインドします。プロパティを依存関係プロパティにすることを忘れないでください(技術的には必須ではありませんが、役立ちます)。ViewModelはINotifyProperty変更を実装し、PropertyChangedイベントを発生させてバインディングを更新する必要があります。
EditPersonCommandに問題があると思います(正常に起動しません)。relayCommandで確認すると機能します。
これはコードです:
ViewModel:
public class PersonViewModel : ViewModelBase
{
private PersonModel _PersonModel;
private ICommand _EditPersonCommand;
///<remarks>
/// must use the parameterless constructor to satisfy <Window.Resources>
///</remarks>
public PersonViewModel()
: this(new PersonModel())
{
}
public PersonViewModel(PersonModel personModel)
{
PersonModelProp = personModel;
}
public ICommand EditPersonCommand
{
get
{
if (_EditPersonCommand == null)
{
_EditPersonCommand = new RelayCommand(ExecuteEditPerson,CanExecuteEditPerson);
}
return _EditPersonCommand;
}
}
private bool CanExecuteEditPerson(object parameter)
{
PersonModel p = parameter as PersonModel;
return (p != null) && (p.Age > 0);
}
private void ExecuteEditPerson(object o)
{
}
public PersonModel PersonModelProp
{
get
{
return _PersonModel;
}
set
{
_PersonModel = value;
NotifyPropertyChanged("PersonModelProp");
}
}
}
そしてこのRelayCommand(火災イベントは大丈夫です!)
public class RelayCommand : ICommand
{
#region Constants and Fields
private readonly Predicate<object> canExecute;
private readonly Action<object> execute;
#endregion
#region Constructors and Destructors
public RelayCommand(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
if (execute == null)
{
throw new ArgumentNullException("execute");
}
this.execute = execute;
this.canExecute = canExecute;
}
#endregion
#region Events
public event EventHandler CanExecuteChanged
{
add
{
CommandManager.RequerySuggested += value;
}
remove
{
CommandManager.RequerySuggested -= value;
}
}
#endregion
#region Implemented Interfaces
#region ICommand
[DebuggerStepThrough]
public bool CanExecute(object parameter)
{
return this.canExecute == null || this.canExecute(parameter);
}
public void Execute(object parameter)
{
this.execute(parameter);
}
#endregion
#endregion
}
Xmal:
<Button Content="Edit" HorizontalAlignment="Right" Height="20" Width="80"
CommandParameter="{Binding PersonModelProp}"
Command="{Binding EditPersonCommand}" />