C# 我怎样才能插入一个“;选择全部";组合框顶部的项及其项资源集?
我有一个C# 我怎样才能插入一个“;选择全部";组合框顶部的项及其项资源集?,c#,wpf,xaml,mvvm,combobox,C#,Wpf,Xaml,Mvvm,Combobox,我有一个组合框,其itemsource设置为IList的MyClass对象。我覆盖了组合框的项目模板,在项目旁边显示一个复选框。我想在顶部有一个项目,上面写着“全选”,当用户选中复选框时,代码会选中所有复选框。我的问题是,MVVM是如何做到这一点的 我不想将单独的MyClass对象添加到IList。这似乎会涉及太多视图和模型的耦合。有没有一种方法可以直接在XAML代码中添加一个项,并给它一个检查所有复选框的命令 我现在的组合框是: <ComboBox ItemsSource="{Bindi
组合框
,其itemsource
设置为IList
的MyClass
对象。我覆盖了组合框
的项目模板
,在项目旁边显示一个复选框
。我想在顶部有一个项目,上面写着“全选”,当用户选中复选框时,代码会选中所有复选框。我的问题是,MVVM是如何做到这一点的
我不想将单独的MyClass
对象添加到IList
。这似乎会涉及太多视图和模型的耦合。有没有一种方法可以直接在XAML代码中添加一个项,并给它一个检查所有复选框的命令
我现在的组合框是:
<ComboBox ItemsSource="{Binding MyList}" Width="200">
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding Selected}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
编辑:我找到了一种在XAML代码中使用添加项到集合的方法。当用户选中“全选”项的复选框时,我仍然需要一种运行代码的方法。要仅添加项目,代码如下:
<ComboBox Width="200">
<ComboBox.Resources>
<CollectionViewSource x:Key="comboBoxSource" Source="{Binding Path=MyList}" />
</ComboBox.Resources>
<ComboBox.ItemsSource>
<CompositeCollection>
<local:MyClass Name="Select All" Selected="False">
</local:MyClass>
<CollectionContainer Collection="{Binding Source={StaticResource comboBoxSource}}" />
</CompositeCollection>
</ComboBox.ItemsSource>
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding Selected}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
选择项目时必须注册事件,选择项目时,请检查所选项目是否为第一个项目(使用索引),然后将选择更改为“需要什么”。
(这里没有IDE,很抱歉没有代码)。我个人只需修改复选框的模板,并使用Click handler在那里添加自定义复选框,没有什么太花哨的东西,很容易理解
从中可以修改此零件:
<ScrollViewer Margin="4,6,4,6"
SnapsToDevicePixels="True">
<StackPanel IsItemsHost="True"
KeyboardNavigation.DirectionalNavigation="Contained" />
</ScrollViewer>
并将自定义对象添加到IList。这将很好地工作,没有任何废话,您的viewmodel对view没有概念,+它是可测试的。对每个人来说都是双赢的 无论何时按下“全选”按钮,您都可以调用操作,绑定到itemssource,在整个集合中枚举,并将选定值设置为true。此解决方案需要混合界面
<local:MyClass Name="Select All" Selected="False">
<i:Interaction.Triggers>
<ic:DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, Path=Selected}" Value="True">
<local:SelectAll TargetObject="{Binding RelativeSource={RelativeSource AncestorType=ComboBox}, Path=ItemsSource}"/>
</ic:DataTrigger>
</i:Interaction.Triggers>
</local:MyClass>
然后创建类SelectAll,如下所示
public class SelectAll : TargetedTriggerAction<List<MyClass>>
{
protected override void Invoke(object parameter)
{
if (Target is List<MyClass>)
foreach (var elem in (List<MyClass>)Target)
elem.Selected = true;
}
}
public类SelectAll:TargetedTriggerAction
{
受保护的覆盖无效调用(对象参数)
{
如果(目标是列表)
foreach(var elem in(列表)目标)
elem.Selected=true;
}
}
我想出了一种使用一些简单概念的方法
我的第一个问题是,我想在列表的顶部添加一个“全选”项目,而不是实际将一个项目添加到数据库IList
。我编辑了我的原始帖子,以表明我可以使用CompositeCollection
来完成这项工作。我使“全选”数据绑定对象成为MyClass
的子类,并将该类称为MyClassSelectAll
。下面将对此进行详细介绍
我的第二个问题是,我需要处理复选框。与常规MyClass
项目不同,单击“全选”项目的事件。我给每个复选框
一个命令
,我可以用它来检查复选框
。为此,我需要对用户单击的IList
和复选框
进行引用(更具体地说,是绑定到该复选框的MyClass
对象)
我发现解决第二个问题的一种方法是将复选框.CommandParameter
设置为包含这两个对象的多绑定。在命令.Execute(object)
方法中,我可以轻松地检查当前的MyClass
是否是MyClassSelectAll
,如果是,我可以遍历IList
列表(不包含“全选”项),并适当地设置“Selected”属性
以下是我的相关XAML代码:
<Grid.Resources>
<local:MyCommand x:Key="kMyCommand" />
<local:MyConverter x:Key="kConv" />
</Grid.Resources>
<ComboBox Width="200">
<ComboBox.Resources>
<CollectionViewSource x:Key="comboBoxSource" Source="{Binding Path=MyList}" />
</ComboBox.Resources>
<ComboBox.ItemsSource>
<CompositeCollection>
<local:MyClassSelectAll Name="Select All" Selected="False" />
<CollectionContainer Collection="{Binding
Source={StaticResource comboBoxSource}}" />
</CompositeCollection>
</ComboBox.ItemsSource>
<ComboBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}"
IsChecked="{Binding Selected}"
Command="{StaticResource kMyCommand}">
<CheckBox.CommandParameter>
<MultiBinding Converter="{StaticResource kConv}">
<Binding RelativeSource="{RelativeSource
FindAncestor, AncestorType={x:Type Window}}"
Path="DataContext.MyList" />
<Binding Path="." />
</MultiBinding>
</CheckBox.CommandParameter>
</CheckBox>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
我用来传递MyList
和CurrentItem
引用的MyCommandArgs
类是一个简单的容器类,所以我不会在这里发布它
MyClassSelectAll
是最简单的;它唯一的任务是将“selectall”MyClass
对象标记为selectall对象
class MyClassSelectAll : MyClass
{
}
最后是处理单击事件的MyCommand
对象
class MyCommand : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
var mylist = parameter as MyCommandArgs;
if (mylist != null && mylist.CurrentItem is MyClassSelectAll)
{
foreach (var item in mylist.MyList)
{
item.Selected = mylist.CurrentItem.Selected;
}
}
}
}
谢谢大家。我真的被困在这上面了。似乎很多时候,当我在WPF中执行某些操作时遇到问题,解决方法是使用转换器这听起来像WinForms的方法。这将导致紧密耦合,正如我在上面提到的在MyList顶部插入项目时所提到的。如果您想使事情复杂化,理论上,您可以创建新的MyClassSelectAll类,并将其添加到CompositeCollection中,为特定类型创建新的DataTemplate,并钩住CheckBoxs CHecked事件。最后,我做了类似于您建议的事情。我使用了一个命令而不是Checked事件。我不确定如何修改复选框模板,我不想更改我的MyClass
class。谢谢你的帮助。
class MyConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
MyCommandArgs result = new MyCommandArgs()
{
MyList = values[0] as IList<MyClass>,
CurrentItem = values[1] as MyClass
};
return result;
}
public object[] ConvertBack(object value, Type[] targetTypes,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
class MyClassSelectAll : MyClass
{
}
class MyCommand : ICommand
{
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
var mylist = parameter as MyCommandArgs;
if (mylist != null && mylist.CurrentItem is MyClassSelectAll)
{
foreach (var item in mylist.MyList)
{
item.Selected = mylist.CurrentItem.Selected;
}
}
}
}