WPF中的EventTrigger

WPF中的EventTrigger,wpf,data-binding,Wpf,Data Binding,我想从通过InvokeCommandAction选中复选框的列表框中获取SelectedItems,并将其存储在obsevableCollection SelectedItems中,但我无法使SelectedItemChangedCommand正常工作(断点未命中),也不确定如何填充SelectedItems集合中的项。我尝试了以下操作,希望一旦选中或取消选中复选框,SelectedItemChangedCommand就会被调用,并且我可以在这里调用一个方法来填充SelectedItems 请注

我想从通过InvokeCommandAction选中复选框的列表框中获取SelectedItems,并将其存储在obsevableCollection SelectedItems中,但我无法使SelectedItemChangedCommand正常工作(断点未命中),也不确定如何填充SelectedItems集合中的项。我尝试了以下操作,希望一旦选中或取消选中复选框,SelectedItemChangedCommand就会被调用,并且我可以在这里调用一个方法来填充SelectedItems

请注意,我正在寻找一种方法来实现这一点没有任何代码落后

 <ListBox Margin="45,7,0,0" VerticalAlignment="Top" Grid.Column="1" Grid.Row="0" Grid.RowSpan="2"
         ItemsSource="{Binding ListItems}"
         SelectionMode="Multiple" Height="146">
    <ListBox.Resources>
        <Style TargetType="ListBoxItem">
            <Setter Property="OverridesDefaultStyle" Value="true" />
            <Setter Property="SnapsToDevicePixels" Value="true" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="ListBoxItem">
                        <CheckBox Margin="5,2"
                                  IsChecked="{TemplateBinding IsSelected}">
                            <ContentPresenter />
                        </CheckBox>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    </ListBox.Resources>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="SelectionChanged">
            <i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}"  CommandParameter="{Binding ElementName=myListBox, Path=SelectedItem}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ListBox>

更新的Xaml文件

<Window x:Class="stack.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:stack"
        xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Window.DataContext>
        <local:MainViewModel/>
    </Window.DataContext>
    <Grid>
        <ListBox x:Name="myListBox" Margin="45,7,0,0" VerticalAlignment="Top" 

                 ItemsSource="{Binding ListItems}"
                 SelectionMode="Multiple" Height="146">
            <ListBox.Resources>
            <Style TargetType="ListBoxItem">
                <Setter Property="OverridesDefaultStyle" Value="true" />
                <Setter Property="SnapsToDevicePixels" Value="true" />
                <Setter Property="Template">
                    <Setter.Value>
                        <ControlTemplate TargetType="ListBoxItem">
                            <CheckBox 
                                Margin="5,2" 
                                IsChecked="{Binding IsSelected, RelativeSource={RelativeSource TemplatedParent}}" 
                            >
                                <ContentPresenter />
                            </CheckBox>
                        </ControlTemplate>
                    </Setter.Value>
                </Setter>
            </Style>
        </ListBox.Resources>
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="SelectionChanged">
                <i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}"  
                                       CommandParameter="{Binding ElementName=myListBox, Path=SelectedItem}"/>
            </i:EventTrigger>
        </i:Interaction.Triggers>
        </ListBox>
    </Grid>
</Window>

我将listbox绑定到视图模型中定义的observableCollection ListItems,如下所示

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace stack
{


    public class MainViewModel : INotifyPropertyChanged
    {
        public ObservableCollection<string> ListItems { get; set; }
        public ObservableCollection<string> SelectedListItems { get; set; }

        public RelayCommand SelectedItemChangedCommand { get; set; }

        public string _selectedItem;
        public string SelectedItem
        {
            get => _selectedItem;
            set
            {
                _selectedItem = value;
                OnPropertyChanged("SelectedItem");
            }
        }

        public bool _isSelected;
        public bool IsSelected
        {
            get => _isSelected;
            set
            {
                _isSelected = value;
                OnPropertyChanged("IsSelected");
            }
        }

        public MainViewModel()
        {
            ListItems = new ObservableCollection<string>();
            ListItems.Add("One");
            ListItems.Add("Two");
            ListItems.Add("three");
            ListItems.Add("Four");
            ListItems.Add("Five");
            SelectedItemChangedCommand = new RelayCommand(this.ExecuteItemChanged);
        }

        public void ExecuteItemChanged(object parameter)
        {
            if (IsSelected)
            {
                SelectedListItems.Add(SelectedItem);
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler _propertyChangedEventHandler = PropertyChanged;
            _propertyChangedEventHandler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}
使用系统;
使用System.Collections.Generic;
使用System.Collections.ObjectModel;
使用系统组件模型;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows.Input;
名称空间堆栈
{
公共类MainViewModel:INotifyPropertyChanged
{
公共ObservableCollection列表项{get;set;}
公共ObservableCollection SelectedListItems{get;set;}
public relay命令选择editemchangedCommand{get;set;}
公共字符串_selectedItem;
公共字符串SelectedItem
{
get=>\u选择编辑项;
设置
{
_选择editem=值;
OnPropertyChanged(“SelectedItem”);
}
}
公营学校选举产生;
公选学校
{
get=>\u被选中;
设置
{
_isSelected=值;
不动产变更(“IsSelected”);
}
}
公共主视图模型()
{
ListItems=新的ObservableCollection();
列表项。添加(“一”);
添加(“两个”);
增加(“三”);
增加(“四”);
增加(“五”);
选择EditemChangedCommand=new RelayCommand(this.ExecuteItemChanged);
}
public void ExecuteItemChanged(对象参数)
{
如果(当选)
{
SelectedListItems.Add(SelectedItem);
}
}
公共事件属性更改事件处理程序属性更改;
受保护的虚拟void OnPropertyChanged(字符串propertyName)
{
PropertyChangedEventHandler\u PropertyChangedEventHandler=PropertyChanged;
_propertyChangedEventHandler?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
}
}

模板绑定
很便宜,但它不做双向绑定。因此,项目不会被选中。您需要使用
模板parent的
相对资源
进行常规绑定:

<CheckBox 
    Margin="5,2" 
    IsChecked="{Binding IsSelected, RelativeSource={RelativeSource TemplatedParent}}" 
    >
并确保列表框上有
x:Name=“myListBox”
:CommandParameter绑定需要它来查找SelectedItems

最后:ExecuteItemChanged()非常脆弱。您的主视图模型属性
已选择
SelectedItem
未绑定到任何内容。它们永远都是假的和空的。每次选择更改时,您都会执行该命令并将第一个选定项作为
参数
传入,然后忽略它并查看
false
是否仍然是
false
,它就是。否则,viewmodel的SelectedItem属性仍将为空,因为您也从未更新过该属性

您要做的是:当选择更改时,将当前选定项的整个集合传递到您的命令中。用控件中的当前状态替换viewmodel当前选定项的整个集合。您必须,必须,必须绑定SelectedItems作为上面的CommandParameter

去掉viewmodel上的
SelectedItem
IsSelected
,它们没有任何作用

如果可能的话,千万不要涉足维护两个列表并试图使它们零碎地保持同步的业务。总是一团糟。在这种情况下你不需要这么做

public void ExecuteItemChanged(object parameter)
{
    //  ListBox.SelectedItems is System.Windows.Controls.SelectedItemCollection,
    //  a precambrian monster that's declared internal in PresentationFramework.dll. 
    //  However, it does implement non-generic IList, so cast it to that. 
    if (parameter is System.Collections.IList selectedItems)
    {
        if (SelectedListItems == null)
        {
            SelectedListItems = new ObservableCollection<String>();
        }

        SelectedListItems.Clear();

        foreach (string item in selectedItems)
        {
            SelectedListItems.Add(item);
        }
    }
}
public void ExecuteItemChanged(对象参数)
{
//ListBox.SelectedItems是System.Windows.Controls.SelectedItemCollection,
//在PresentationFramework.dll中声明为内部的前寒武纪怪物。
//但是,它确实实现了非通用的IList,所以将其转换为该类。
if(参数为System.Collections.IList selectedItems)
{
如果(SelectedListItems==null)
{
SelectedListItems=新的ObservableCollection();
}
SelectedListItems.Clear();
foreach(selectedItems中的字符串项)
{
SelectedListItems。添加(项);
}
}
}

谢谢,我根据您的建议更新了Xaml文件,但仍然无法填充所选项目:-(,我已将已完成的ViewModel类粘贴到此处。我想我缺少了其他内容
ExecuteItemChanged(对象参数)
已断开。viewmodel的
SelectedItem
属性是什么?Null。它未绑定。您要麻烦地将列表框中的第一个选定项作为
参数传入
public void ExecuteItemChanged(object parameter)
{
    //  ListBox.SelectedItems is System.Windows.Controls.SelectedItemCollection,
    //  a precambrian monster that's declared internal in PresentationFramework.dll. 
    //  However, it does implement non-generic IList, so cast it to that. 
    if (parameter is System.Collections.IList selectedItems)
    {
        if (SelectedListItems == null)
        {
            SelectedListItems = new ObservableCollection<String>();
        }

        SelectedListItems.Clear();

        foreach (string item in selectedItems)
        {
            SelectedListItems.Add(item);
        }
    }
}