Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataGridComboBoxColumn different ItemsSource for different rows

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.

enter image description here

As you all see in my code there are different teachers for different classes. When I click on say 9th class,

enter image description here

"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.

enter image description here

enter image description here

So without changing the other rows can I update the row I wanted.....

like image 779
Gopi Avatar asked Sep 08 '16 16:09

Gopi


2 Answers

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.

like image 190
Rachel Avatar answered Sep 18 '22 21:09

Rachel


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>
like image 39
JMB Avatar answered Sep 21 '22 21:09

JMB