2016-09-08 2 views
2

Here Вопрос, аналогичный моему вопросу, задан, но я не нашел решение там.DataGridComboBoxColumn разные ItemsSource для разных строк

Мой вопрос: Как связать разные данные (например, списки) с «DataGridComboBoxColumn» для каждого ComboBox в разных строках. Вот код, который я попытался

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; } 
} 

, когда я запускаю этот код, выход, как показано ниже.

enter image description here

Как вы видите в моем коде есть разные учителя для разных классов. Когда я нажимаю на сказать 9-го класса,

enter image description here

"listTeachersNine" должны быть добавлены к "gTeachers.ItemsSource". Но если я это сделаю

gTeachers.ItemsSource = listTeachersNine; 

все остальные строки действуют. Как я могу сделать это без изменений в других строках. Пожалуйста, дайте мне некоторое представление ... Спасибо заранее

UPDATE:

Даже если я попробовал это ниже код

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; 

      } 
     } 

Я попытался как комментировал часть и раскомментируйте часть, но не использовать его. Когда я запускаю свое приложение, он показывает, как показано выше на первой диаграмме. Но при нажатии на определенную строку все остальные данные строк исчезают. Но дело в том, что он обновляет данные новых учителей. Посмотрите ниже две фотографии.

enter image description here

enter image description here

Так, не меняя остальные строки можно обновить строку, я хотел .....

ответ

1

Там несколько способов, я могу думать, чтобы сделать это.

Если вы не заботитесь о строгом дизайне MVVM, вы можете использовать IValueConverter, передать ему свой КЛАСС и преобразовать конвертер в список, который нужно вернуть. Что-то вдоль линий

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.

<DataGridTemplateColumn Header="TEACHERS"> 
    <DataGridTemplateColumn.CellTemplate> 
     <DataTemplate> 
      <ComboBox ItemsSource="{Binding CLASS, Converter={StaticResource TestConverter}}" 
         SelectedItem="{Binding TEACHER}" /> 
     </DataTemplate> 
    </DataGridTemplateColumn.CellTemplate> 
</DataGridTemplateColumn> 

Другим альтернативным решением было бы добавить в список 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<string> ValidTeachers { get; set; } 
} 

Вы также нуждались бы Изменить событие так при каждом изменении класса, ValidTeachers массив обновляется.

Я уверен, что есть другие варианты, которые могут быть более чистыми, но если вы ищете что-то простое и легкое, я бы порекомендовал один из них.

+0

Второе решение довольно хорошее и простое. В ближайшее время я попробую его обновить. Спасибо :) – Gopi

+0

См. Мой обновленный вопрос. – Gopi

+0

@Gopi 'gTeachers' является' DataGridComboBoxColumn', поэтому установка 'ItemsSource' применяется ко всем строкам. Вы только хотите установить «ItemsSource» для выбранной строки. Я бы предложил конвертер, как я написал в своем ответе. Возможно, вы сможете написать код, чтобы найти «ComboBox» в выбранной строке, чтобы изменить это, но было бы сложнее, на мой взгляд. – Rachel

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; 
    } 
+0

@Makul Varshney Ваш код образец работает хорошо для привязки конкретного списка к конкретному Combobox.Но я получаю исключение «Путь или XPath» с двусторонней привязкой. Теперь я работаю над этим исключением. Обновите вас, как только я закончу свою работу. Спасибо :) – Gopi

0

Заканчивать ответ here по Vincent Sibal - MSFT:

Это должно помочь вам с установкой ItemsSource одного столбца в определенной строке на основе выбор в другом столбце той же строки. Он использует стили для установки ItemsSource каждый раз, когда вы нажимаете на ComboBox для редактирования значения.

Вот пример, приведенный в указанном выше сайте, в случае, ссылка будет удалена в будущем:

Примера есть если у меня есть DataGrid, и я хочу, выбор в столбце Current Категории влияют параметры в DataGridComboBoxColumn, называемые Current Product.

Элементы в коллекции/списке ProductsInCategory служат в качестве выбираемых значений для столбца Current Product. Элементы в этом списке расположены в инкубаторе для CurrentCategory, как показано ниже:

public int CurrentCategory 
{  
    get { return _currentCategory; } 

    set 
    { 
     _currentCategory = value; 

     ProductsInCategory = DBAccess.GetProductsInCategory(_currentCategory).Tables["Products"].DefaultView; 
     OnPropertyChanged("CurrentCategory"); 
    } 

} 

Ниже XAML, который будет использоваться для подключения текущего продукта ItemsSource заново каждый раз, когда CurrentCategory выбор изменяется.

<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> 
+0

Можете ли вы скопировать или привести ссылки на соответствующие части ссылки в своем ответе? Связи, как правило, удаляются со временем. –

+0

@MarioTacke Done. – JMB

Смежные вопросы