DataGridComboBoxColumn用于不同行的不同ItemsSource

这里提出类似于我的问题的问题,但我没有在那里找到解决方案。

我的问题:如何将不同数据(比如Lists)绑定到不同行中每个ComboBox的“DataGridComboBoxColumn”。 这是我试过的代码

XAML:

          

的.cs

 using System.Collections.ObjectModel; // For ObservableCollection public partial class MainWindow : Window { ObservableCollection listTeachersSix = null; ObservableCollection listTeachersSeven = null; ObservableCollection listTeachersEight = null; ObservableCollection listTeachersNine = null; ObservableCollection listTeachersTen = null; ObservableCollection listSubjects = null; ObservableCollection listPeriods = null; public MainWindow() { InitializeComponent(); listTeachersSix = new ObservableCollection(); listTeachersSeven = new ObservableCollection(); listTeachersEight = new ObservableCollection(); listTeachersNine = new ObservableCollection(); listTeachersTen = new ObservableCollection(); listSubjects = new ObservableCollection(); listPeriods = new ObservableCollection(); listTeachersSix.Add("Vijay"); listTeachersSix.Add("Naveen"); listTeachersSix.Add("Gopal"); listTeachersSix.Add("Somesh"); listTeachersSeven.Add("Raj"); listTeachersSeven.Add("Rama Krishna"); listTeachersSeven.Add("Rakesh"); listTeachersSeven.Add("Ram Babu"); listTeachersEight.Add("Murali"); listTeachersEight.Add("Ritesh"); listTeachersEight.Add("Nagesh"); listTeachersEight.Add("Tarun"); listTeachersNine.Add("Bhaskar"); listTeachersNine.Add("Babji"); listTeachersNine.Add("Bhanu"); listTeachersNine.Add("Balaji"); listTeachersTen.Add("Lal"); listTeachersTen.Add("Mohan"); listTeachersTen.Add("Raj Sekhar"); listTeachersTen.Add("Sunil"); for (int i = 0; i <= 8; i++) listPeriods.Add(i); listSubjects.Add("Maths"); listSubjects.Add("Physics"); listSubjects.Add("Social"); listSubjects.Add("English"); listSubjects.Add("Hindi"); listSubjects.Add("Telugu"); List listTimeTable = new List() { new Info () { CLASS="6", PERIOD=1, TEACHER="Vijay", SUBJECT="Maths" }, new Info () { CLASS="7", PERIOD=5, TEACHER="Raj", SUBJECT="Physics" }, new Info () { CLASS="8", PERIOD=7, TEACHER="Murali", SUBJECT="Social" }, new Info () { CLASS="10", PERIOD=4, TEACHER="Mohan", SUBJECT="English" }, new Info () { CLASS="6", PERIOD=8, TEACHER="Naveen", SUBJECT="Maths" }, new Info () { CLASS="9", PERIOD=3, TEACHER="Bhaskar", SUBJECT="Hindi" }, new Info () { CLASS="8", PERIOD=6, TEACHER="Ritesh", SUBJECT="English" }, new Info () { CLASS="10", PERIOD=2, TEACHER="Lal", SUBJECT="Social" } }; dg_TimeTable.ItemsSource = listTimeTable; gPeriods.ItemsSource = listPeriods; gSubjects.ItemsSource = listSubjects; gTeachers.ItemsSource = listTeachersSix; } } public class Info { public string CLASS { get; set; } public int PERIOD { get; set; } public string SUBJECT { get; set; } public string TEACHER { get; set; } } 

当我运行此代码时,输​​出如下。

在此处输入图像描述

正如你们在我的代码中看到的那样,不同的class级有不同的教师。 当我点击说第9课时,

在此处输入图像描述

应将“listTeachersNine”添加到“gTeachers.ItemsSource”中 。 但如果我这样做

 gTeachers.ItemsSource = listTeachersNine; 

所有其他行都有效。 如何在不更改其他行的情况下执行此操作。 请给我一些想法…提前谢谢

更新:

即使我尝试了以下代码

  private void dg_TimeTable_SelectionChanged(object sender, SelectionChangedEventArgs e) { int num = (sender as DataGrid).SelectedIndex; try { if (num == 0) { //listTeachersSix.Clear(); //listTeachersSix.Add("Vijay"); //listTeachersSix.Add("Naveen"); //listTeachersSix.Add("Gopal"); //listTeachersSix.Add("Somesh"); gTeachers.ItemsSource = listTeachersSix; } else if (num == 1) { //listTeachersSix.Clear(); //listTeachersSix.Add("Raj"); //listTeachersSix.Add("Rama Krishna"); //listTeachersSix.Add("Rakesh"); //listTeachersSix.Add("Ram Babu"); gTeachers.ItemsSource = listTeachersSeven; } else if (num == 2) { //listTeachersSix.Clear(); //listTeachersSix.Add("Murali"); //listTeachersSix.Add("Ritesh"); //listTeachersSix.Add("Nagesh"); //listTeachersSix.Add("Tarun"); gTeachers.ItemsSource = listTeachersEight; } } 

我尝试了注释部分和未注释部分,但没有用。 当我运行我的应用程序时,它显示如上面的第一个图表。 但是当点击特定行时,所有其他行数据都在消失。 但事实是,它正在更新新的教师数据。 看下面的两张照片。

在此处输入图像描述

在此处输入图像描述

因此,如果不更改其他行,我可以更新我想要的行…..

我可以通过几种方式来做到这一点。

如果您不关心严格的MVVM设计,可以使用IValueConverter ,将其传递给CLASS,并让转换器找出要返回的列表。 有点像

 public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { string key = value as string; switch (key) { case "1": return SomethingStatic.TeacherList1; case "2": return SomethingStatic.TeacherList2; ... } } 

如果你想让它变得动态并避免你的转换器中的硬编码列表引用,你可以使用IMultiValueConverter并将变量数组作为另一个绑定值传递它并调整代码以简单地从另一个边界传入的数组中找到正确的ItemsSource值。

请注意,要使用其中任何一个,您可能必须从DataGridComboBoxColumn切换到DataGridTemplateColumn因为绑定将无法从ComboBoxColumn正常工作。

        

另一种替代解决方案是将ValidTeachers列表添加到每个DataRow的项目中,在您的情况下为Info对象。

 public class Info { public string CLASS { get; set; } public int PERIOD { get; set; } public string SUBJECT { get; set; } public string TEACHER { get; set; } public List ValidTeachers { get; set; } } 

您还需要一个Change Event,因此每当CLASS更改时, ValidTeachers数组都会更新。

我确信还有其他选择可能更干净,但如果你正在寻找简单易用的东西,我会推荐其中一种。

查看Vincent Sibal的答案- MSFT :

这应该可以帮助您根据同一行的另一列中的选择设置某一行中某列的ItemsSource。 每次单击ComboBox编辑值时,都使用样式设置ItemsSource。

以下是上述网站提供的示例,以防将来删除链接:

例如,如果我有一个DataGrid,并且我希望在标记为Current Category的列中进行选择,以影响名为Current Product的DataGridComboBoxColumn中的选项。

ProductsInCategory集合/列表中的项目用作“当前产品”列的可选值。 此列表中的项目在CurrentCategory的setter中设置,如下所示:

 public int CurrentCategory { get { return _currentCategory; } set { _currentCategory = value; ProductsInCategory = DBAccess.GetProductsInCategory(_currentCategory).Tables["Products"].DefaultView; OnPropertyChanged("CurrentCategory"); } } 

下面是每当更改CurrentCategory选择时将用于重新连接Current Product ItemsSource的xaml。

         

请参阅链接msdn链接

我现在不能花太多时间。 我拿了你的原始代码并添加到它。 它不完整但会省去一些努力。

XAML

                        

C#代码

  private void dg_TimeTable_PreparingCellForEdit(object sender, DataGridPreparingCellForEditEventArgs e) { int rowIndex = dg_TimeTable.SelectedIndex; if (e.Column == colTeacherList) { FrameworkElement element = e.EditingElement; ComboBox cb = GetVisualChild(element); if (cb != null) { switch(dg_TimeTable.SelectedIndex) { case 1: cb.ItemsSource = listTeachersSeven; break; case 2: cb.ItemsSource = listTeachersEight; break; default: cb.ItemsSource = listTeachersSix; break; } } } } static T GetVisualChild(Visual parent) where T : Visual { T child = default(T); int numVisuals = VisualTreeHelper.GetChildrenCount(parent); for (int i = 0; i < numVisuals; i++) { Visual v = (Visual)VisualTreeHelper.GetChild(parent, i); child = v as T; if (child == null) { child = GetVisualChild(v); } if (child != null) { break; } } return child; }