如何删除绑定到bool []数组的复选框的Click处理程序

时间:2013-08-18 10:31:02

标签: c# wpf xaml mvvm

数据上下文类:

class ImageHandler : INotifyPropertyChanged
{
    bool[] directions = new bool[8];

    public bool[] Directions { get { return directions; } }

    // ...
}

XAML:

<UniformGrid Columns="8">
    <CheckBox Content=" N" IsChecked="{Binding Path=Directions[0]}" Click="CheckBox_Click"/>
    <CheckBox Content="NW" IsChecked="{Binding Path=Directions[1]}" Click="CheckBox_Click"/>
    <CheckBox Content=" W" IsChecked="{Binding Path=Directions[2]}" Click="CheckBox_Click"/>
    <!-- ... -->
</UniformGrid>

代码背后:

private void CheckBox_Click(object sender, RoutedEventArgs e)
{
     imageHandler.UpdateImage();
}

所以,我在数据上下文类中有布尔数组,并且8个复选框绑定到每个数组成员。 Click事件处理程序根据新的directions数组状态重新计算图像。如何更改此代码以删除CheckBox_Click事件处理程序,使其按照MVVM模式工作?我需要一种方法来检测directions数组中的更改,而无需编写事件处理程序。

2 个答案:

答案 0 :(得分:1)

您需要使用ItemsControl。它消除了在XAML中逐个手动添加UI元素的需要,并且不再需要事件处理程序。

视图模型:

class ImageHandler : INotifyPropertyChanged
{
    List<Direction> directions = new List<Direction>();
    public List<Direction> Directions { get { return directions; } }
    // ...

    public ImageHandler()
    {
       Directions.Add(new Direction {DisplayName = " N" });
       Directions.Add(new Direction {DisplayName = "NW" });
       Directions.Add(new Direction {DisplayName = " W" });
       //.. Etc

       Directions.ForEach(x => x.OnIsSelectedChanged = OnDirectionSelectionChanged);
    }

    private void OnDirectionSelectionChanged(Direction direction)
    {
       //.. Your logic here
    }
}

数据项:

public class Direction: INotifyPropertyChanged
{
   private bool _isSelected;
   public bool IsSelected
   {
       get { return _isSelected; }
       set
       {
           _isSelected = value;
           if (OnIsSelectedChanged != null)
               OnIsSelectedChanged(this);

           NotifyPropertyChange(() => IsSelected);
       }
   }

   public string DisplayName {get;set;}

   public Action<Direction> OnIsSelectedChanged {get;set;}
}

XAML:

<ItemsControl ItemsSource="{Binding Directions}">
   <ItemsControl.ItemsPanel>
      <ItemsPanelTemplate>
          <UniformGrid Columns="8"/>
      </ItemsPanelTemplate>      
   </ItemsControl.ItemsPanel>

   <ItemsControl.ItemTemplate>
       <DataTemplate>
           <CheckBox Content="{Binding DisplayName}" IsChecked="{Binding IsSelected}"/>
       </DataTemplate>
   </ItemsControl.ItemTemplate>
</ItemsControl>

旁注:MVVM不是关于无代码,也不是删除事件处理程序。它是关于UI所属的UI,以及Data所属的Data,以及这两者之间的中间层(ViewModel)。因此,只要您将逻辑保留在ViewModel中(通过在事件处理程序中委托ViewModel.DoSomething()),您当前基于事件的方法不会破坏MVVM。

答案 1 :(得分:1)

然后WPF复选框具有Command属性,您可以将其绑定到视图模型中的ICommand(使用RelayCommand),并且还传递参数以查看哪个复选框(在您的情况下为绑定项)已更新。

我的另一个建议是改变XAML,如果你确定你的viewmodel会决定你的UniformGrid中显示什么,即它是否总是从viewmodel呈现数据,那么你也可以在你的UniformGrid中定义ItemsControl,然后定义一个ItemTemplate的模板,这样你也不需要在XAML中将你的复选框与定义的索引绑定,而不是在以后维护它