5

コマンド パラメーター バインディングの仕組みを理解するのに苦労しています。

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

2 に答える 2

4

InitializeCompenent は、ファイルに関連付けられた xaml を処理します。CommandParameter バインディングが最初に処理されるのは、この時点です。InitializeCompenent の前にフィールドを初期化すると、プロパティは null になりません。その後に作成すると、null になります。

InitializeCompenent の後にウィジェットを作成する場合は、依存関係プロパティを使用する必要があります。依存関係プロパティは、CommandParameter が更新される原因となる通知を生成するため、null にはなりません。

TestWidget を依存関係プロパティにする方法のサンプルを次に示します。

public static readonly DependencyProperty TestWidgetProperty =
    DependencyProperty.Register("TestWidget", typeof(Widget), typeof(Window1), new UIPropertyMetadata(null));
public Widget TestWidget
{
    get { return (Widget) GetValue(TestWidgetProperty); }
    set { SetValue(TestWidgetProperty, value); }
}
于 2008-11-02T22:37:34.603 に答える
0

依存関係プロパティを使用しても、評価されるコマンドの CanExecute を強制するには、CommandManager.InvalidateRequerySuggested を呼び出す必要があります。

于 2008-12-22T06:00:24.383 に答える