DataGridComboBoxColumn不同行

时间:2016-09-08 16:04:30

标签: c# wpf wpfdatagrid datagridcomboboxcolumn

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

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

enter image description here

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

enter image description here

应将

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

            }
       }

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

enter image description here

enter image description here

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

3 个答案:

答案 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)

here查看答案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选项时将用于重新连接当前产品项目源的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;
    }