多个列表的选定项目

时间:2017-02-15 18:02:23

标签: c# wpf

我有一个组类,其中包含一个项目列表和一个标题:

public class MyGroup {     
    public MyGroup(string _header){
        header = _header;
    }

    protected string header = "";
    public string Header
    {
        get { return header; }
    }

    protected List<MyGroupItem> item = new List<MyGroupItem>();
    public List<MyGroupItem> Item
    {
        get { return item; }
    }
}

public class MyGroupItem {       
    public MyGroupItem(string _name, double _multiplier){
        name = _name;
        multiplier = _multiplier;
    }

    protected double multiplier = 1.0;

    protected string name = "";
    public string Name
    {
        get { return name; }
    }
}

到目前为止一切顺利。在我的主要课程中,我有一个可观察的小组集合,我填充它:

protected ObservableCollection<MyGroup> groups = new ObservableCollection<MyGroup>();
public ObservableCollection<MyGroup> Groups
{
    get { return groups; }
}

protected MyGroupItem currentItem;
public MyGroupItem CurrentItem
{
    get { return currentItem; }
    set
    {
       if (currentItem== value) return;
       currentItem= value;
       NotifyPropertyChanged("CurrentItem");
    }
}

....

var GroupA = new MyGroup("Group A");
GroupA.MyGroupItem.Add("Item 1", 1.0);
Groups.Add(GroupA);

currentItem = GroupA.MyGroupItem[0];

以上所有内容只是简单地展示了我如何设置我的类和可观察列表。现在,我切换到xaml。

<ItemsControl ItemsSource="{Binding Path=Groups}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Background="Transparent" ClipToBounds="True" Orientation="Vertical"></StackPanel>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type local:MyGroup}">
            <StackPanel>
                <TextBlock Text="{Binding Path=Header}"></TextBlock>
                <ListView ItemsSource="{Binding Path=MyGroupItem}" SelectedItem="{Binding Path=DataContext.CurrentItem, ElementName=ControlRoot}">
                    <ListView.ItemTemplate>
                        <DataTemplate DataType="local:MyGroupItem">
                            <TextBlock Text="{Binding Path=Name}"></TextBlock>
                        </DataTemplate>
                     </ListView.ItemTemplate>
                 </ListView>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

所以,基本上我有一个显示多个项目列表的ItemControl。控件应放置组名称的标题,然后显示该组中特定项目的列表视图。布局工作得很好......但是,当我处理 选定项目 时会出现问题。基本上,列表视图允许我选择多个组中的一个组中的项目...这意味着我可以在任何给定时间选择多个项目。例如,假设我选择了组A中的第一项。但是,然后我将我的选择更改为组B中的第二项。因为组B是一个单独的列表,它允许我激活该项...但它不会取消选择A组中的项目。我想要的是这个多列表组作为单个列表。这可能吗?我是否需要设置单独的 SelectionChanged 事件?如果是这样,我将如何确保何时更改选项以清除所有列表中的所选项目并仅显示用户刚刚选择的正确项目?

1 个答案:

答案 0 :(得分:1)

您应该在视图模型类中处理此问题。

如果添加属性以将每个组的选定项目保存到MyGroup类并实现INotifyPropertyChanged接口,则可以处理CollectionChanged Groups事件在视图模型类中收集以设置CurrentItem属性,同时通过在此事件处理程序中将其设置为SelectedItem来清除其他组的null属性。

这是一个例子。

<强> MyGroup.cs:

public class MyGroup : INotifyPropertyChanged
{
    public MyGroup(string _header)
    {
        header = _header;
    }

    protected string header = "";
    public string Header
    {
        get { return header; }
    }

    protected List<MyGroupItem> item = new List<MyGroupItem>();
    public List<MyGroupItem> Item
    {
        get { return item; }
    }

    private MyGroupItem _item;
    public MyGroupItem SelectedItem
    {
        get { return _item; }
        set { _item = value; NotifyPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

}

<强> MyGroupItem.cs:

public class MyGroupItem
{
    public MyGroupItem(string _name, double _multiplier)
    {
        name = _name;
        multiplier = _multiplier;
    }

    protected double multiplier = 1.0;

    protected string name = "";
    public string Name
    {
        get { return name; }
    }
}

查看型号:

public class Window1ViewModel : INotifyPropertyChanged
{
    public Window1ViewModel()
    {
        groups.CollectionChanged += (s, e) =>
        {
            if (e.NewItems != null)
            {
                foreach (object item in e.NewItems)
                {
                    (item as INotifyPropertyChanged).PropertyChanged
                        += new PropertyChangedEventHandler(item_PropertyChanged);
                }
            }

            if (e.OldItems != null)
            {
                foreach (object item in e.OldItems)
                {
                    (item as INotifyPropertyChanged).PropertyChanged
                        -= new PropertyChangedEventHandler(item_PropertyChanged);
                }

            };
        };

        var GroupA = new MyGroup("Group A");
        GroupA.Item.Add(new MyGroupItem("Item 1", 1.0));
        GroupA.Item.Add(new MyGroupItem("Item 2", 1.0));
        GroupA.Item.Add(new MyGroupItem("Item 3", 1.0));
        Groups.Add(GroupA);

        var GroupB = new MyGroup("Group B");
        GroupB.Item.Add(new MyGroupItem("Item 1", 1.0));
        GroupB.Item.Add(new MyGroupItem("Item 2", 1.0));
        GroupB.Item.Add(new MyGroupItem("Item 3", 1.0));
        Groups.Add(GroupB);

        currentItem = GroupA.Item[0];
    }

    private bool _handle = true;
    private void item_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        if (!_handle)
            return;

        MyGroup group = sender as MyGroup;
        CurrentItem = group.SelectedItem;

        //clear the selection in the other groups:
        _handle = false;
        foreach (MyGroup g in Groups)
            if (g != group)
                g.SelectedItem = null;
        _handle = true;
    }

    protected ObservableCollection<MyGroup> groups = new ObservableCollection<MyGroup>();
    public ObservableCollection<MyGroup> Groups
    {
        get { return groups; }
    }

    protected MyGroupItem currentItem;
    public MyGroupItem CurrentItem
    {
        get { return currentItem; }
        set
        {
            if (currentItem == value) return;
            currentItem = value;
            NotifyPropertyChanged("CurrentItem");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}

查看:

<ItemsControl ItemsSource="{Binding Path=Groups}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <StackPanel Background="Transparent" ClipToBounds="True" Orientation="Vertical"></StackPanel>
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate DataType="{x:Type local:MyGroup}">
            <StackPanel>
                <TextBlock Text="{Binding Path=Header}"></TextBlock>
                <ListView ItemsSource="{Binding Path=Item}" 
                                  SelectedItem="{Binding SelectedItem}">
                    <ListView.ItemTemplate>
                        <DataTemplate DataType="local:MyGroupItem">
                            <TextBlock Text="{Binding Path=Name}"></TextBlock>
                        </DataTemplate>
                    </ListView.ItemTemplate>
                </ListView>
            </StackPanel>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>