Here提出类似于我的问题的问题,但我没有在那里找到解决方案。
我的问题:如何将不同数据(比如Lists)绑定到不同行中每个ComboBox的“DataGridComboBoxColumn”。这是我试过的代码
XAML:
<Grid>
<DataGrid x:Name="dg_TimeTable" AutoGenerateColumns="False" Margin="0,0,0,97" ColumnWidth="*">
<DataGrid.Columns>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding CLASS}" Header="CLASS" />
<DataGridComboBoxColumn Header="PERIOD" x:Name="gPeriods" SelectedValueBinding="{Binding PERIOD, Mode=TwoWay}" DisplayMemberPath="{Binding PERIOD}" />
<DataGridComboBoxColumn Header="TEACHERS" x:Name="gTeachers" SelectedValueBinding="{Binding TEACHER, Mode=TwoWay}" DisplayMemberPath="{Binding TEACHER}" />
<DataGridComboBoxColumn Header="SUBJECTS" x:Name="gSubjects" SelectedValueBinding="{Binding SUBJECT, Mode=TwoWay}" DisplayMemberPath="{Binding SUBJECT}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
的.cs
using System.Collections.ObjectModel; // For ObservableCollection
public partial class MainWindow : Window
{
ObservableCollection<string> listTeachersSix = null;
ObservableCollection<string> listTeachersSeven = null;
ObservableCollection<string> listTeachersEight = null;
ObservableCollection<string> listTeachersNine = null;
ObservableCollection<string> listTeachersTen = null;
ObservableCollection<string> listSubjects = null;
ObservableCollection<int> listPeriods = null;
public MainWindow()
{
InitializeComponent();
listTeachersSix = new ObservableCollection<string>();
listTeachersSeven = new ObservableCollection<string>();
listTeachersEight = new ObservableCollection<string>();
listTeachersNine = new ObservableCollection<string>();
listTeachersTen = new ObservableCollection<string>();
listSubjects = new ObservableCollection<string>();
listPeriods = new ObservableCollection<int>();
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<Info> listTimeTable = new List<Info>()
{
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; }
}
当我运行此代码时,输出如下。
正如你们在我的代码中看到的那样,不同的班级有不同的教师。当我点击说第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;
}
}
我尝试了评论部分和未注释部分,但没有用。当我运行我的应用程序时,它显示如上面的第一个图表。但是当点击特定行时,所有其他行数据都在消失。但问题是,它正在更新新的教师数据。看下面两张图片。
因此,如果不更改其他行,我可以更新我想要的行.....
答案 0 :(得分:2)
我有几种方法可以做到这一点。
如果您不关心严格的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
,因为绑定无法从{{1}正常工作}。
ComboBoxColumn
另一种替代解决方案是将<DataGridTemplateColumn Header="TEACHERS">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding CLASS, Converter={StaticResource TestConverter}}"
SelectedItem="{Binding TEACHER}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
的列表添加到每个DataRow的项目中,在您的情况下为ValidTeachers
对象。
Info
您还需要更改事件,因此每当CLASS更改时,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<string> ValidTeachers { get; set; }
}
数组都会更新。
我确定其他选项可能更干净,但如果您正在寻找简单易用的东西,我建议您使用其中一种。
答案 1 :(得分:2)
这可以帮助您根据同一行的另一列中的选择设置某一行中某列的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选项时将用于重新连接当前产品项目源的xaml。
<dg:DataGridComboBoxColumn Header="Current Product"
SelectedValueBinding="{Binding Path=CurrentProduct}"
SelectedValuePath="ProductID"
DisplayMemberPath="ProductName">
<dg:DataGridComboBoxColumn.ElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=ProductsInCategory}" />
</Style>
</dg:DataGridComboBoxColumn.ElementStyle>
<dg:DataGridComboBoxColumn.EditingElementStyle>
<Style TargetType="ComboBox">
<Setter Property="ItemsSource" Value="{Binding Path=ProductsInCategory}" />
</Style>
</dg:DataGridComboBoxColumn.EditingElementStyle>
</dg:DataGridComboBoxColumn>
答案 2 :(得分:0)
请参阅链接msdn link
我现在不能花太多时间。我拿了原始代码并加入其中。它不完整,但会省去一些努力。
XAML
<Grid>
<DataGrid x:Name="dg_TimeTable" AutoGenerateColumns="False" Margin="0,0,0,97" ColumnWidth="*" PreparingCellForEdit="dg_TimeTable_PreparingCellForEdit">
<DataGrid.Columns>
<DataGridTextColumn IsReadOnly="True" Binding="{Binding CLASS}" Header="CLASS" />
<DataGridComboBoxColumn Header="PERIOD" x:Name="gPeriods" SelectedValueBinding="{Binding PERIOD, Mode=TwoWay}" DisplayMemberPath="{Binding PERIOD}" />
<DataGridComboBoxColumn Header="TEACHERS" x:Name="gTeachers" SelectedValueBinding="{Binding TEACHER, Mode=TwoWay}" DisplayMemberPath="{Binding TEACHER}" />
<DataGridTemplateColumn Header="TEACHERS" x:Name="colTeacherList" >
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=TEACHER, Mode=TwoWay, UpdateSourceTrigger=LostFocus}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<ComboBox Name="cmbTeacherList" SelectedItem="{Binding myItem, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
<DataGridComboBoxColumn Header="SUBJECTS" x:Name="gSubjects" SelectedValueBinding="{Binding SUBJECT, Mode=TwoWay}" DisplayMemberPath="{Binding SUBJECT}"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
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<ComboBox>(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<T>(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<T>(v);
}
if (child != null)
{
break;
}
}
return child;
}