使用复选框绑定(全选)

时间:2012-03-28 07:42:30

标签: wpf xaml binding

我想实现一个复选框,它可以作为select-all / unselect-all复选框,但是我遇到了一些绑定问题。我对XAML和WPF并不陌生,所以对我来说,为什么我的代码不能正常工作,这是一个谜。我希望你能提供帮助。这就是我在做的事情:

首先,我使用MVVMLight和事件到命令标记。

我的视图名为SetupView.xaml,我的视图模型名为SetupViewModel.cs

public class SetupViewModel : ViewModelBase
{
    private List<FilterOptions> m_informationToShow;
    private FilterOptions m_currentSelection;

    public List<FilterOptions> InformationToShow
    {
        get { return m_informationToShow; }
        set
        {
            m_informationToShow = value;
            RaisePropertyChanged("InformationToShow");
            RaisePropertyChanged("InformationToShowCount");
        }
    }

    public FilterOptions CurrentSelection
    {
        get { return m_currentSelection; }
        set
        {
            m_currentSelection = value;
            RaisePropertyChanged("CurrentSelection");
        }
    }
}

FilterOptions-object是我的模型对象。因为您需要了解其中的一部分才能理解问题,这里显示了解决问题所需的部分:

public class FilterOptions
{
    private string m_projectName;

    private BugsFilter m_bugsFilter;
    private BuildsFilter m_buildsFilter;
    private ChangeSetsFilter m_changeSetsFilter;
    private ProgressInfoFilter m_progressInfoFilter;
    private RisksFilter m_risksFilter;

    private bool m_projectHealthFilter;

    public bool AllFilterValues
    {
        get
        {
            if (m_bugsFilter.AtLeastOneFieldEnabled() ||
                m_buildsFilter.AtLeastOneFieldEnabled() ||
                m_changeSetsFilter.AtLeastOneFieldEnabled() ||
                m_progressInfoFilter.AtLeastOneFieldEnabled() ||
                m_risksFilter.AtLeastOneFieldEnabled() ||
                m_projectHealthFilter
                )
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        set
        {
            if (value == false)
            {
                m_bugsFilter.NoInformation();
                m_buildsFilter.NoInformation();
                m_changeSetsFilter.NoInformation();
                m_progressInfoFilter.NoInformation();
                m_risksFilter.NoInformation();
                m_projectHealthFilter = false;
            }
            else
            { 
                m_bugsFilter.CompleteInformation();
                m_buildsFilter.CompleteInformation();
                m_changeSetsFilter.CompleteInformation();
                m_progressInfoFilter.CompleteInformation();
                m_risksFilter.CompleteInformation();
                m_projectHealthFilter = true;
            }
        }
    }

我将继续我的观点:

<UserControl.Resources>
    <viewModels:SetupViewModel x:Key="thisViewModel"></viewModels:SetupViewModel>

    <DataTemplate x:Key="ProjectEntryTemplate">
        <Border Margin="75,20,5,0">
            <CheckBox Name="naam" Content="{Binding ProjectName}"
                      FontFamily="Segoe UI"
                      FontWeight="Light"
                      FontSize="24"
                      IsChecked="{Binding AllFilterValues}"
                      DataContext="{Binding}">
                <i:Interaction.Triggers>
                    <i:EventTrigger EventName="Checked">
                        <mvvm:EventToCommand Command="{Binding ProjectListItemCheckedChanged, Source={StaticResource thisViewModel}}"
                                             PassEventArgsToCommand="True"/>
                    </i:EventTrigger>
                    <i:EventTrigger EventName="Unchecked">
                        <mvvm:EventToCommand Command="{Binding ProjectListItemCheckedChanged, Source={StaticResource thisViewModel}}"
                                             PassEventArgsToCommand="True"/>
                    </i:EventTrigger>
                </i:Interaction.Triggers>
            </CheckBox>
        </Border> 
    </DataTemplate>
</UserControl.Resources>

正如您所看到的,我在列表框中使用了一个数据模板:

<ListBox ItemsSource="{Binding InformationToShow}"
                            ItemTemplate="{StaticResource ProjectEntryTemplate}" 
                            SelectedIndex="0"
                            BorderThickness="0">
                    <i:Interaction.Triggers>
                        <i:EventTrigger EventName="SelectionChanged">
                            <mvvm:EventToCommand Command="{Binding SelectionListboxChanged}" 
                                                    PassEventArgsToCommand="True"/>
                        </i:EventTrigger>
                    </i:Interaction.Triggers>
                </ListBox>

除此之外,我在同一个窗口,在右侧的另一个网格中,有很多复选框。它们都对应于FilterOptions对象中的给定过滤器。这就是我在我看来所做的事情:

<StackPanel Orientation="Vertical"
                                Margin="0,5,0,5">
                        <CheckBox Name="activeBugs" Content="Active bugs"
                                  FontFamily="Segoe UI"
                                  FontWeight="Light"
                                  FontSize="22"
                                  IsChecked="{Binding CurrentSelection.BugsFilter.ActiveBugs}">
                        </CheckBox>

                        <CheckBox Name="resolvedBugs" Content="Resolved bugs"
                                  FontFamily="Segoe UI"
                                  FontWeight="Light"
                                  FontSize="22"
                                  IsChecked="{Binding CurrentSelection.BugsFilter.ResolvedBugs}"/>
                        <CheckBox Name="bugTrend" Content="Bug trend"
                                  FontFamily="Segoe UI"
                                  FontWeight="Light"
                                  FontSize="22"
                                  IsChecked="{Binding CurrentSelection.BugsFilter.BugTrend}"/>
                    </StackPanel>

最后但并非最不重要的是,这是我在视图模型中的命令功能:

RelayCommand m_selectionChanged;
    public ICommand SelectionListboxChanged
    {
        get
        {
            if (m_selectionChanged == null)
                m_selectionChanged = new RelayCommand(param => SelectionListboxChangedExec(param), param => true);

            return m_selectionChanged;
        }
    }

    private void SelectionListboxChangedExec(object param)
    {
        SelectionChangedEventArgs e = (SelectionChangedEventArgs)param;
        ListBox b = (ListBox)e.Source;
        CurrentSelection = (FilterOptions)b.SelectedItem;
    }

    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    RelayCommand m_projectCheckedChanged;
    public ICommand ProjectListItemCheckedChanged
    {
        get
        {
            if (m_projectCheckedChanged == null)
                m_projectCheckedChanged = new RelayCommand(param => ProjectListItemCheckedChangedExec(param), param => true);

            return m_projectCheckedChanged;
        }
    }

    private void ProjectListItemCheckedChangedExec(object param)
    {
        RoutedEventArgs e = (RoutedEventArgs)param;
        CheckBox checkBox = (CheckBox)e.Source;
        FilterOptions dataContext = (FilterOptions)checkBox.DataContext;

        if ((bool)checkBox.IsChecked)
            dataContext.AllFilterValues = true;
        else
        {
            dataContext.AllFilterValues = false;
        }

        //var expression = checkBox.GetBindingExpression(ToggleButton.IsCheckedProperty);
        //expression.UpdateSource();
    }

我真的找不到问题。有没有人可以帮助我? 非常感谢您的帮助!!

提前谢谢大家!

1 个答案:

答案 0 :(得分:0)

为什么要用命令来做?将复选框绑定到内部通知父BindingOption的{​​{1}}类,此通知实际上不属于视图,而是属于视图模型。

ViewModel不应该知道视图使用CheckBox。

所以你应该做的是,各个选项都有一个通知ViewModel属性绑定到IsSelected es,为每个属性提供对父CheckBox的引用,并通知当前ViewModel更改时的父级。在View中执行此操作,虽然您可以找到很多方法,但您不应该这样做,MVVM是关于将视图任务与viewmodel-tasks分开。

这样也可以控制“全选”,“取消全选”或“反转选择”等。

相关问题