【问题标题】:Binding with checkbox (select all)与复选框绑定(全选)
【发布时间】:2012-03-28 07:42:30
【问题描述】:

我想实现一个复选框,该复选框用作全选/全选复选框,但我遇到了一些绑定问题。我对 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 对象是我的模型对象。因为你需要它来理解问题,这里显示你需要理解问题的部分:

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();
    }

我真的找不到问题。有谁能帮助我吗? 非常感谢您的帮助!

提前谢谢大家!

【问题讨论】:

    标签: wpf xaml binding


    【解决方案1】:

    为什么你必须用命令来做呢?将复选框绑定到内部通知父级ViewModelBindingOption 类,此通知实际上不属于视图,而是属于视图模型。

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

    那么你应该做什么让各个选项有一个通知IsSelected属性绑定到CheckBoxes,为每个选项提供对父ViewModel的引用,并在当前IsSelected时通知父被改变了。在视图中执行此操作,虽然您可以找到很多方法,但您不应该这样做,MVVM 是将视图任务与视图模型任务分开。

    这种方式还可以让您控制“全选”、“取消全选”或“反转选择”等。

    【讨论】:

    • 即使我不使用命令,它仍然无法正常工作。我确实正确绑定了所有内容,但问题仍然存在......
    • 嗯,我认为一定有一个错误,因为: private void SelectionListboxChangedExec(object param) { SelectionChangedEventArgs e = (SelectionChangedEventArgs)param;列表框 b = (列表框)e.Source; CurrentSelection = (FilterOptions)b.SelectedItem; CurrentSelection.ProjectName = "ba"; RaisePropertyChanged("CurrentSelection");可以正常工作,但是当我绑定时它没有更新......
    • @JoshMulholland,我不完全理解什么没有更新,请用代码扩展你的问题并评论它什么不起作用,请在这里评论,所以我会收到通知你的更新。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-26
    • 1970-01-01
    • 2019-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多