Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何获取所选列表框项目以更新另一个列表框?_C#_Wpf_Mvvm - Fatal编程技术网

C# 如何获取所选列表框项目以更新另一个列表框?

C# 如何获取所选列表框项目以更新另一个列表框?,c#,wpf,mvvm,C#,Wpf,Mvvm,我是wpf和mvvm的新手,我希望这是有意义的 我有一个复选框项目列表框。当我勾选或取消勾选一个项目时,我想知道如何触发一个事件或任何能让我将所选项目文本添加到不同列表框的东西 以下是我迄今为止所做的工作: XAML: <ListBox ItemsSource="{Binding Target}" IsEnabled="{Binding IsControlEnabled}"> <ListBox.ItemTemplate> <DataTe

我是wpf和mvvm的新手,我希望这是有意义的

我有一个复选框项目列表框。当我勾选或取消勾选一个项目时,我想知道如何触发一个事件或任何能让我将所选项目文本添加到不同列表框的东西

以下是我迄今为止所做的工作:

XAML:

<ListBox ItemsSource="{Binding Target}" IsEnabled="{Binding IsControlEnabled}">
     <ListBox.ItemTemplate>
          <DataTemplate>
                <CheckBox Content="{Binding TitleName}" IsChecked="{Binding IsChecked}" />
          </DataTemplate>
     </ListBox.ItemTemplate>
</ListBox>
private ObservableCollection<CheckServerItem> _target = new ObservableCollection<CheckServerItem>();
public class CheckServerItem : ViewModelBase
{
    private bool _isChecked { get; set; }
    private string _Title { get; set; }

    public bool IsChecked
    {
        get { return _isChecked; }
        set
        {
            _isChecked = value;
            RaisePropertyChanged("IsChecked");
        }
    }
    public string TitleName
    {
        get { return _Title; }
        set
        {
            _Title = value;
            RaisePropertyChanged("TitleName");
        }
    }
}
这个小类正确地处理了这些检查,但是我不知道如何让这个类调用主ViewModel类中管理另一个ListBox的方法,或者我应该做什么


谢谢你的帮助

我建议将另一个列表框的ItemsSource绑定到同一个ObservableCollection,然后使用转换器只获取所选项目。这样,您就根本不必处理附加和分离事件处理程序的问题。转换器应为:

[ValueConversion(typeof(object), typeof(object))]
public class IsCheckedConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        ObservableCollection<CheckServerItem> result = new ObservableCollection<CheckServerItem>();
        foreach(CheckServerItem item in (value as ObservableCollection<CheckServerItem>))
        {
            if (item.IsChecked)
            {
                result.Add(item);
            }
        }
        return result;
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return Binding.DoNothing;
    }
}
[ValueConversion(typeof(object),typeof(object))]
公共类IsCheckedConverter:IValueConverter
{
公共对象转换(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性)
{
ObservableCollection结果=新的ObservableCollection();
foreach(CheckServerItem-in(值为ObservableCollection))
{
如果(项目已检查)
{
结果.添加(项目);
}
}
返回结果;
}
公共对象转换回(对象值、类型targetType、对象参数、System.Globalization.CultureInfo区域性)
{
不做任何事;
}
}
您需要将转换器放在应用程序或窗口的“资源”部分,以便在列表框中使用它:

<this:IsCheckedConverter x:Key="MyIsCheckedConverter" />

然后,另一个列表框的ItemsSource的绑定如下所示:

<ListBox ItemsSource="{Binding Target, Converter={StaticResource MyIsCheckedConverter}}>
...
xmlns:acb="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"
...
<ListBox ItemsSource="{Binding Target}"
         IsEnabled="{Binding IsControlEnabled}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding TitleName}"
                      IsChecked="{Binding IsChecked}">
                <acb:CommandBehaviorCollection.Behaviors>
                    <acb:BehaviorBinding Event="Checked"
                                         Command="{Binding DataContext.SelectionChangedCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                                         CommandParameter="{Binding}" />
                    <acb:BehaviorBinding Event="Unchecked"
                                         Command="{Binding DataContext.SelectionChangedCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                                         CommandParameter="{Binding}" />
                </acb:CommandBehaviorCollection.Behaviors>
            </CheckBox>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我建议使用ICommand并使用AttachedCommand行为将其绑定到复选框的选中RoutedEvent(您可以在nuget上获得):

xaml的外观如下所示:

<ListBox ItemsSource="{Binding Target, Converter={StaticResource MyIsCheckedConverter}}>
...
xmlns:acb="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"
...
<ListBox ItemsSource="{Binding Target}"
         IsEnabled="{Binding IsControlEnabled}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <CheckBox Content="{Binding TitleName}"
                      IsChecked="{Binding IsChecked}">
                <acb:CommandBehaviorCollection.Behaviors>
                    <acb:BehaviorBinding Event="Checked"
                                         Command="{Binding DataContext.SelectionChangedCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                                         CommandParameter="{Binding}" />
                    <acb:BehaviorBinding Event="Unchecked"
                                         Command="{Binding DataContext.SelectionChangedCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                                         CommandParameter="{Binding}" />
                </acb:CommandBehaviorCollection.Behaviors>
            </CheckBox>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>
viewmodel中的命令可能类似于:

private DelegateCommand<CheckServerItem> selectionChangedCommand;

    public DelegateCommand<CheckServerItem> SelectionChangedCommand
    {
        get
        {
            return this.selectionChangedCommand ?? (this.selectionChangedCommand = new DelegateCommand<CheckServerItem>((x) =>
            {
                if (x.IsChecked)
                {
                    MyOtherList.Add(x);
                } else
                {
                    MyOtherList.Remove(x);
                }
            }));
        }
    }
private DelegateCommand selectionChangedCommand;
公共委派命令选择更改命令
{
得到
{
返回this.selectionChangedCommand???(this.selectionChangedCommand=new DelegateCommand((x)=>
{
如果(x.I检查)
{
添加(x);
}否则
{
MyOtherList.Remove(x);
}
}));
}
}

根据菲利波·维加尼的回答,如果您仅通过鼠标选中/取消选中复选框,您还可以执行以下操作:

        <ListBox.ItemTemplate>
            <DataTemplate>
                <CheckBox Content="{Binding TitleName}"
                          IsChecked="{Binding IsChecked}"
                          Command="{Binding DataContext.SelectionChangedCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"
                          CommandParameter="{Binding}" />
            </DataTemplate>
        </ListBox.ItemTemplate>


一种方法是在viewmodel中添加事件以侦听复选框另一个列表框也使用相同的MainViewModel?@SamTheDev,另一个列表框在MainViewModel中。我个人不会这样做,因为这种类型的筛选是您希望进行单元测试的主要候选项,或者至少能够在虚拟机中创建临时代码,并能够在调试器中单步执行,而不让视图碍事。就我个人而言,我会向主视图模型添加第二个集合,并在其中进行过滤,以响应IsChecked属性的更改。我只会在其他列表框满足某种功能要求的情况下向VM添加第二个集合(即,进行了进一步的选择,并使用辅助选择完成了某些操作)。我想象这个二级列表框只是在视图中起作用,它只是向用户说明选择了哪些项目。我以前也经历过这种情况,为了满足非功能性需求而尝试同步列表和注册/取消注册事件处理程序(并引入可能的内存泄漏)对我来说似乎不值得。这个选项看起来最有趣,但我不确定在MainViewModel中绑定的属性是什么。你能帮我吗@shahjahan?