将ListView项链接到单独的不同列表

时间:2012-09-25 19:40:06

标签: wpf listview itemssource

我已经定义了一个ListView,其中每个项目都以只读方式显示(即仅限选择,不是TextBoxComboBox(根据ItemTemplate )。

可以从这些组合框中选择一个可能的项目列表。但需要注意的是,一次两个组合框中不能选择任何项目。为了确保这一点,一旦在其中一个组合框中选择了一个项目,它必须从所有其他组合框中删除(显然除了选择它的那个),并且一旦取消选择它,就必须添加它再次到所有其他组合框。

哦,还有一件事:与完整列表相比,可见项目的顺序不得改变。

我的问题是:我该如何实现这种行为?

我已经尝试了三种可能的解决方案:

  • 我编写了一个新的帮助器控件类,它通过绑定到外部世界获取现有项目的完整列表和排除(使用过的)项目列表,以及所选项目的属性。我可以在ItemTemplate中包含该控件类;然后,该模板中的组合框将其ItemsSource属性绑定到助手类的ItemsProvider属性,该属性应该将现有项目列表,排除项目列表和所选项目绑定在一起。返回该特定组合框的单个枚举项 但是,我在所有关于列表更改的更新通知中都丢失了;我担心我必须对两个输入列表中的NotifyCollectionChangedAction的所有组合做出单独的反应,并且考虑到有十几种更新方法,我认为这不是正确的方法。
  • 我将现有项目列表更改为存储布尔值以及每个项目的列表,因此我可以将每个项目标记为隐藏或不隐藏。这样可以减轻我在保持项目顺序的同时获得被排除项目列表的必要性,从而减少上述组合变更通知的复杂性。
    不幸的是,由于列表本身不随该解决方案而改变,我不知道如何让依赖属性基础结构通知我的助手类中的ItemsSource属性。
  • 我不必须使用绑定方式的WPF;我也可以在这里做代码隐藏。因此,我尝试遍历所有ListViewItem并检索每个ListViewItem的组合框以手动刷新项目列表。但是,在加载项目模板后,我找不到访问ListView.ItemContainerGenerator s的好时机。对于这种情况似乎没有事件,ItemContainerGenerator是只读的,所以即使ItemContainerGenerator不是密封的类,我也无法分配我自己的专用OnApplyTemplate会创建我可以覆盖{{1}}的自定义列表视图项。

2 个答案:

答案 0 :(得分:0)

我可能会将所有ComboBoxes绑定到源集合上的不同CollectionViews,这会过滤掉其他ComboBoxes的所选项目。如果组合框的选择发生变化,您还需要Refresh视图。

答案 1 :(得分:0)

如果将列表绑定到ViewModel中的不同列表,并绑定所选项以触发更改这些列表的方法,则可以获得结果。与以下类似。

MainWindow.xaml的Xaml:

<Window x:Class="ComboBox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" >
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="180" />
            <ColumnDefinition Width="180" />
            <ColumnDefinition Width="180" />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="26" />
        </Grid.RowDefinitions>
        <ComboBox Name="cboOne" Grid.Column="0" Grid.Row="0" ItemsSource="{Binding CboOneList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValue="{Binding CboOneValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></ComboBox>
        <ComboBox Name="cboTwo" Grid.Column="1" Grid.Row="0" ItemsSource="{Binding CboTwoList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValue="{Binding CboTwoValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></ComboBox>
        <ComboBox Name="cboThree" Grid.Column="2" Grid.Row="0" ItemsSource="{Binding CboThreeList, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValue="{Binding CboThreeValue, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"></ComboBox>
    </Grid>
</Window>

MainWindow.xaml的代码隐藏:

using System.Windows;
using System.Windows.Controls;

namespace ComboBox {
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window {
    public MainWindow() {
        InitializeComponent();

        this.DataContext = new ComboBoxViewModel();

    }

    private void cboOne_SelectionChanged(object sender, SelectionChangedEventArgs e) {

    }
}
}

视图模型:

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.ComponentModel;

 namespace ComboBox {
class ComboBoxViewModel : INotifyPropertyChanged {
    public event PropertyChangedEventHandler PropertyChanged;
    List<string> master = new List<string>() { "A", "B", "C", "D", "E", "F" };

    #region C'tor
    public ComboBoxViewModel() {
        RetrieveLists();
    }
    #endregion

    #region Methods
    protected void OnPropertyChanged(String propertyName) {
        PropertyChangedEventHandler handler = this.PropertyChanged;
        if(null != handler) {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    public void RetrieveLists() {
        List<string> tempOne = (from a in master
                                where !a.Equals(CboTwoValue) && !a.Equals(CboThreeValue)
                                select a).ToList();
        CboOneList = tempOne;

        List<string> tempTwo = (from a in master
                                where !a.Equals(CboOneValue) && !a.Equals(CboThreeValue)
                                select a).ToList();
        CboTwoList = tempTwo;

        List<string> tempThree = (from a in master
                                where !a.Equals(CboTwoValue) && !a.Equals(CboOneValue)
                                select a).ToList();
        CboThreeList = tempThree;
    }
    #endregion

    #region Properties
    private string cboOneValue = string.Empty;
    public string CboOneValue {
        get {
            return cboOneValue;
        }
        set {
            if(!value.Equals(cboOneValue)) {
                cboOneValue = value;
                RetrieveLists();
                OnPropertyChanged("CboOneValue");
            }
        }
    }
    private string cboTwoValue = string.Empty;
    public string CboTwoValue {
        get {
            return cboTwoValue;
        }
        set {
            if(!value.Equals(cboTwoValue)) {
                cboTwoValue = value;
                RetrieveLists();
                OnPropertyChanged("CboTwoValue");
            }
        }
    }
    private string cboThreeValue = string.Empty;
    public string CboThreeValue {
        get {
            return cboThreeValue;
        }
        set {
            if(!value.Equals(cboThreeValue)) {
                cboThreeValue = value;
                RetrieveLists();
                OnPropertyChanged("CboThreeValue");
            }
        }
    }

    private List<string> cboOneList = new List<string>();
    public List<string> CboOneList {
        get {
            return cboOneList;
        }
        set {
            cboOneList = value;
            OnPropertyChanged("CboOneList");
        }
    }

    private List<string> cboTwoList = new List<string>();
    public List<string> CboTwoList {
        get {
            return cboTwoList;
        }
        set {
            cboTwoList = value;
            OnPropertyChanged("CboTwoList");
        }
    }

    private List<string> cboThreeList = new List<string>();
    public List<string> CboThreeList {
        get {
            return cboThreeList;
        }
        set {
            cboThreeList = value;
            OnPropertyChanged("CboThreeList");
        }
    }
    #endregion
}

}