2008-11-02 109 views
5

我在理解命令参数绑定的工作原理时遇到了一些麻烦。WPF CommandParameter绑定问题

当我在调用InitializeComponent之前创建一个widget类的实例时,它似乎工作正常。对ExecuteCommand函数中参数(Widget)的修改将被“应用”到_widget。这是我期望的行为。

如果_widget的实例是在InitializeComponent之后创建的,那么我会在ExecuteCommand函数中获得e.Parameter的空引用异常。

这是为什么?如何使用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

InitializeCompenent处理与该文件关联的xaml。正是在这个时候,CommandParameter绑定首先被处理。如果您在InitializeCompenent之前初始化您的字段,那么您的属性不会为空。如果你在创建它之后它是空的。

如果你想在InitializeCompenent之后创建widget,那么你将需要使用一个依赖属性。依赖项proeprty会引发一个通知,导致CommandParameter被更新,因此它不会为空。

以下是如何使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); } 
} 
0

即使依赖属性,你仍然需要调用CommandManager.InvalidateRequerySuggested强制命令的CanExecute被评估。