开发者

CheckBox in ItemTemplate causes NullReferenceException for Command binding

Belo开发者_如何学运维w is a simple sample app. The checkbox in the ItemTemplate has a command binding which seems to be what is causing the problem. When I try to run it I get a NullReferenceException ( at Microsoft.Practices.Composite.Presentation.Commands.DelegateCommand`1.System.Windows.Input.ICommand.CanExecute ...). Why does this happen?

MainWindow.xaml:

<Window x:Class="CheckBoxCommandTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">
  <StackPanel x:Name="stackPanel">
      <ItemsControl ItemsSource="{Binding CheckBoxes}">
          <ItemsControl.ItemTemplate>
              <DataTemplate>
                  <CheckBox Content="{Binding Name}" 
                            IsChecked="{Binding IsSelected}"
                            Command="{Binding DataContext.CheckBoxCommand, ElementName=stackPanel}"
                            CommandParameter="{Binding Parameter}" />
              </DataTemplate>
          </ItemsControl.ItemTemplate>
      </ItemsControl>
  </StackPanel>
</Window>

MainWindow.xaml.cs

public partial class MainWindow : Window, INotifyPropertyChanged
{
    public MainWindow()
    {
        InitializeComponent();
        CheckBoxCommand = new DelegateCommand<int>(OnCheckBoxChecked);

        CheckBoxes = new List<CheckBoxModel>()
                         {
                             new CheckBoxModel { Name = "Checkbox #1", Parameter = 1 },
                             new CheckBoxModel { Name = "Checkbox #2", Parameter = 2 },
                         };
        TriggerPropertyChanged("CheckBoxes");
    }

    public List<CheckBoxModel> CheckBoxes { get; set; }

    public ICommand CheckBoxCommand { get; set; }

    private void OnCheckBoxChecked(int i) { /* Do nothing */ }
}

CheckBoxModel.cs

public class CheckBoxModel
{
    public string Name { get; set; }
    public bool IsSelected { get; set; }
    public int Parameter { get; set; }
}


This is most likely happening because you're using a value type for your command parameter, along with a Binding for the Parameter. When the template is first loaded, the Bindings haven't evaluated yet so the CommandParameter property (of type object) is initially (and only temporarily) assigned a null value. When it is bound (in this case just before the CommandParameter), the DelegateCommand then tries to use the null parameter as an int, which is normally fine when the parameter is a reference type but obviously invalid for value types like int.

You may be able to fix the error by just changing the parameter type to int? and checking HasValue in your command handlers.


When I have done this I always use a CanExecute method to determine if the command is allowed to execute, maybe its required, couldnt say though without looking into it more but try add something like:

private bool CanExecuteOnCheckBoxChecked(int notUsed) { return true; }

Change your delegate to :

CheckBoxCommand = new DelegateCommand(OnCheckBoxChecked,CanExecuteOnCheckBoxChecked);

in private void OnCheckBoxChecked put:

if(CanExecuteOnCheckBoxChecked(i) { // Do whatever you want to do }

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜