我想实现一个复选框,它可以作为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();
}
我真的找不到问题。有没有人可以帮助我? 非常感谢您的帮助!!
提前谢谢大家!
答案 0 :(得分:0)
为什么要用命令来做?将复选框绑定到内部通知父BindingOption
的{{1}}类,此通知实际上不属于视图,而是属于视图模型。
ViewModel
不应该知道视图使用CheckBox。
所以你应该做的是,各个选项都有一个通知ViewModel
属性绑定到IsSelected
es,为每个属性提供对父CheckBox
的引用,并通知当前ViewModel
更改时的父级。在View中执行此操作,虽然您可以找到很多方法,但您不应该这样做,MVVM是关于将视图任务与viewmodel-tasks分开。
这样也可以控制“全选”,“取消全选”或“反转选择”等。