2012-09-25 78 views
-1

我已經定義了一個ListView其中每個項目顯示爲只讀(即只有選擇,沒有TextBoxComboBox(按照ItemTemplate)。鏈接ListView項目以單獨不同的列表

可以從這些組合框中選擇可能的項目的給定列表。但是,需要注意的是,一次不能在兩個組合框中選擇項目。爲了確保這一點,一旦在其中一個組合框中選擇了一個項目,它必須從所有其他組合框中移除(顯然除了它被選擇的組合框之外),一旦它被取消選擇,它必須被添加到所有其他組合框。

哦,還有一件事:可見項目的順序不能與完整列表相比。

我的問題是:我該如何做到這一點?

我已經試過了,我便想起了三種可能的解決方案:

  • 我寫了一個新的輔助控制類,它現有項目的完整列表,並通過排除(使用)的項目清單綁定到外部世界,以及所選項目的屬性。我可以在ItemTemplate中包含那個控制類;那麼該模板中的組合框將綁定其ItemsSource屬性到助理類的ItemsProvider屬性,該屬性應該將現有項目列表,排除項目列表和所選項目連接在一起,並返回單個項目枚舉特定的組合框。
    但是,我不知何故迷失在關於列表更改的所有更新通知中;我擔心我必須對兩個輸入列表的所有組合NotifyCollectionChangedAction單獨作出反應,並且有可能有十幾種更新方法,但我認爲這不可能是正確的方法。
  • 我將現有項目的列表更改爲與每個項目一起存儲布爾值的列表,因此我可以將每個項目標記爲隱藏或不隱藏。這將使我無需在保持項目順序的同時列出排除的項目,從而減少上述組合變更通知的複雜性。
    不幸的是,由於列表本身並沒有隨該解決方案而改變,我不知道如何讓依賴屬性基礎結構通知我的助手類中的我的ItemsSource屬性。
  • 我不要必須用綁定方式使用WPF;我也可以在這裏做代碼隱藏。所以,我嘗試遍歷所有ListViewItem s並檢索每個組合框以手動刷新項目列表。但是,我們無法找到加載項目模板後訪問ListViewItem的好時機。這種情況似乎沒有事件發生,並且ListView.ItemContainerGenerator是隻讀的,所以即使ItemContainerGenerator不是密封的類,我也不能指定自己的專用ItemContainerGenerator來創建自定義列表視圖項,我可以覆蓋OnApplyTemplate
+0

這已經問,儘管發現這將是一個挑戰。 。 –

+0

@ H.B .:可能。如果我發現了一個類似的問題和答案,我不會問,雖然我確信其他人一定也遇到過類似的問題。 –

+0

請原諒downvote? –

回答

0

我可能會綁定所有ComboBoxes不同CollectionViews在源收集其過濾掉其他ComboBoxes的選擇項。如果組合框的選擇更改,則還需要Refresh視圖。

+0

'CollectionView'是我缺少的鏈接;我設法用'ListCollectionView'來完成它。 –

0

如果將列表綁定到ViewModel中的不同列表,並綁定選定的項目以觸發更改這些列表的方法,那麼您可以獲得結果。類似於下面。

的XAML MainWindow.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 
} 

}