Here the question similar to my question is asked, but I did not find the solution there.
My Question : How to bind different data(say Lists) to the "DataGridComboBoxColumn" for each ComboBox in a different rows. Here is the code I tried
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; }
}
when I run this code, the output is as below.
As you all see in my code there are different teachers for different classes. When I click on say 9th class,
"listTeachersNine" should be added to the "gTeachers.ItemsSource". But if I do so
gTeachers.ItemsSource = listTeachersNine;
all the other rows are effecting. How can I do this without change in the other rows. Please give me some idea... Thanks in advance
UPDATE :
Even though I tried this below code
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;
}
}
I tried both commented part and uncommented part but its no use. When I run my application starting it shows as above first diagram. But when click on particular row, all the other rows data are vanishing. But the thing is, it is updating the new teachers data. Look at the below two pictures.
So without changing the other rows can I update the row I wanted.....
There's a few ways I can think to do this.
If you don't care about strict MVVM design, you could use a IValueConverter
, pass it your CLASS, and have the converter figure out which list to return. Something along the lines of
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;
...
}
}
If you want to make it dynamic and avoid hardcoded list references in your Converter, you could use an IMultiValueConverter
and pass it the variable arrays as another bound value and tweak the code to simply find the right ItemsSource from the array passed in from the other bound values.
Note that to use either of these, you'll probably have to switch from a DataGridComboBoxColumn
to a DataGridTemplateColumn
because the bindings won't work correctly from the ComboBoxColumn
.
<DataGridTemplateColumn Header="TEACHERS">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding CLASS, Converter={StaticResource TestConverter}}"
SelectedItem="{Binding TEACHER}" />
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
Another alternate solution would be to add the list of ValidTeachers
to item for each DataRow, in your case the Info
object.
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; }
}
You'd also need a Change Event so whenever CLASS changes, the ValidTeachers
array gets updated.
I'm sure there's other options that might be cleaner, but if you're looking for something simple and easy I'd recommend one of these.
Check out the answer here by Vincent Sibal - MSFT:
This should help you with setting the ItemsSource of one column in a certain row based on the selection in another column of that same row. It is using styles to set the ItemsSource every time you click on a ComboBox to edit the value.
Here is the example given at the above site, in case the link is removed in the future:
The example is if I have a DataGrid, and I want the selection in a column labeled Current Category to affect the options in the DataGridComboBoxColumn called Current Product.
The items in the ProductsInCategory collection/list serve as the selectable values for the Current Product column. The items in this list are set in the setter for the CurrentCategory, as seen below:
public int CurrentCategory
{
get { return _currentCategory; }
set
{
_currentCategory = value;
ProductsInCategory = DBAccess.GetProductsInCategory(_currentCategory).Tables["Products"].DefaultView;
OnPropertyChanged("CurrentCategory");
}
}
Below is the xaml that will be used to hook up the Current Product ItemsSource anew whenever the CurrentCategory selection is changed.
<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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With