コマンド パラメーター バインディングの仕組みを理解するのに苦労しています。
InitializeComponent を呼び出す前にウィジェット クラスのインスタンスを作成すると、正常に動作するようです。ExecuteCommand 関数のパラメーター (Widget) への変更は、_widget に「適用」されます。これは私が期待した動作です。
InitializeComponent の後に _widget のインスタンスを作成すると、ExecuteCommand 関数で e.Parameter の null 参照例外が発生します。
どうしてこれなの?ビューが作成された後にバインドされたオブジェクトが作成される可能性があるMVPパターンでこれを機能させるにはどうすればよいですか?
public partial class WidgetView : Window
{
RoutedCommand _doSomethingCommand = new RoutedCommand();
Widget _widget;
public WidgetView()
{
_widget = new Widget();
InitializeComponent();
this.CommandBindings.Add(new CommandBinding(DoSomethingCommand, ExecuteCommand, CanExecuteCommand));
}
public Widget TestWidget
{
get { return _widget; }
set { _widget = value; }
}
public RoutedCommand DoSomethingCommand
{
get { return _doSomethingCommand; }
}
private static void CanExecuteCommand(object sender, CanExecuteRoutedEventArgs e)
{
if (e.Parameter == null)
e.CanExecute = true;
else
{
e.CanExecute = ((Widget)e.Parameter).Count < 2;
}
}
private static void ExecuteCommand(object sender, ExecutedRoutedEventArgs e)
{
((Widget)e.Parameter).DoSomething();
}
}
<Window x:Class="CommandParameterTest.WidgetView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="WidgetView" Height="300" Width="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<StackPanel>
<Button Name="_Button" Command="{Binding DoSomethingCommand}"
CommandParameter="{Binding TestWidget}">Do Something</Button>
</StackPanel>
</Window>
public class Widget
{
public int Count = 0;
public void DoSomething()
{
Count++;
}
}