1

数据上下文类:

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,而无需编写事件处理程序。

4

2 回答 2

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)。因此,您当前的基于事件的方法不会破坏 MVVM,只要您将逻辑保留在 ViewModel 中(通过ViewModel.DoSomething()在事件处理程序中进行委托)。

于 2013-08-18T17:32:01.823 回答
1

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

我的另一个建议是也更改 XAML,如果您确定您的视图模型将决定您的 UniformGrid 中显示的内容,即如果它始终呈现来自视图模型的数据,那么您还可以在 UniformGrid 中定义 ItemsControl,然后为 ItemTemplate 定义一个模板这样您也不需要将复选框与 XAML 中定义的索引绑定,以后也不需要维护它

于 2013-08-19T06:30:34.773 回答