C# 在生成的DataGrid中动态使用ComboBox列

C# 在生成的DataGrid中动态使用ComboBox列,c#,wpf,datagrid,C#,Wpf,Datagrid,使用C#WPF,我有一个对话框,它向用户展示了一个包含SQL表名和DataGrid的组合框。在组合框中进行选择时,将检索该表的数据并将其动态显示给DataGrid中的用户。然后,他们可以更改内容、删除行或添加行,并将更改保存回SQL DB 对于一个特定的表,我想使其中一列成为一组已定义值的组合框,这些值当前在枚举中定义。对于该特定表的其他表和其他列,简单的文本字段就可以了 使用本文中的几篇文章,我已经接近了我想要实现的目标,但是我错过了一些阻碍我实现目标的东西(可能很简单)。任何帮助都将不胜感激

使用C#WPF,我有一个对话框,它向用户展示了一个包含SQL表名和DataGrid的组合框。在组合框中进行选择时,将检索该表的数据并将其动态显示给DataGrid中的用户。然后,他们可以更改内容、删除行或添加行,并将更改保存回SQL DB

对于一个特定的表,我想使其中一列成为一组已定义值的组合框,这些值当前在枚举中定义。对于该特定表的其他表和其他列,简单的文本字段就可以了

使用本文中的几篇文章,我已经接近了我想要实现的目标,但是我错过了一些阻碍我实现目标的东西(可能很简单)。任何帮助都将不胜感激

我创建了一个简单的示例程序来演示我试图完成的工作,我在本文中包含了这些代码——即我在AutogeneratingColumn上所做的工作,以将所需的列更改为组合框。到目前为止,我使用的文章有:

对于我的示例程序,我只是以编程方式将数据加载到DataTable中,而不是使用DataAdapter检索值

在我的示例程序中,我可以显示第二列数据和一个空组合框,其中包含显示可能值的下拉列表。但是,不会显示初始值,也不会显示或接受选定值

示例屏幕截图如下:

初始显示:

单击列提供组合框:

所选项目:

移动到另一行:

我的MainWindow.xaml文件如下:

<Window x:Class="DGridTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:System="clr-namespace:System;assembly=mscorlib"
        xmlns:local="clr-namespace:DGridTest"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ObjectDataProvider x:Key="EnumData" MethodName="GetValues" ObjectType="{x:Type System:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:EnumItems"/>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
        <ObjectDataProvider x:Key="Enum1" MethodName="GetValues" ObjectType="{x:Type System:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:ComboItems1"/>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
        <ObjectDataProvider x:Key="Enum2" MethodName="GetValues" ObjectType="{x:Type System:Enum}">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="local:ComboItems2"/>
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    <Grid>
        <DataGrid x:Name="dgrid1" Margin="10,37,10.4,10.4" AutoGeneratingColumn="dgrid1_AutoGeneratingColumn">
            <DataGrid.Columns>
            </DataGrid.Columns>
        </DataGrid>
        <ComboBox x:Name="combo1" HorizontalAlignment="Left" DataContext="{Binding Source={StaticResource EnumData}}" ItemsSource="{Binding Mode=OneWay}" Margin="10,10,0,0" VerticalAlignment="Top" Width="120" SelectionChanged="combo1_SelectionChanged"/>

    </Grid>
</Window>
对于示例,我在SelectionChanged和AutoGenerating列上执行以下操作:

private void combo1_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
    dgrid1.ItemsSource = null;
    dgrid1.Items.Clear();

    if (dataTable != null)
    {
        dataTable.Dispose();
        dataTable = null;
    }

    dataTable = new DataTable("dt");

    if (dataTable != null)
    {
        dataTable.Columns.Add("Col1", typeof(string));
        dataTable.Columns.Add("Col2", typeof(string));

        if (combo1.SelectedValue.ToString() == "Item1")
        {
            DataRow row = dataTable.NewRow();
            row["Col1"] = ComboItems1.Item1B.ToString();
            row["Col2"] = "Item Text : " + ComboItems1.Item1B.ToString();
            dataTable.Rows.Add(row);

            row = dataTable.NewRow();
            row["Col1"] = ComboItems1.Item1A.ToString();
            row["Col2"] = "Item Text : " + ComboItems1.Item1A.ToString();
            dataTable.Rows.Add(row);

            row = dataTable.NewRow();
            row["Col1"] = ComboItems1.Item1D.ToString();
            row["Col2"] = "Item Text : " + ComboItems1.Item1D.ToString();
            dataTable.Rows.Add(row);
        }
        else
        {
            DataRow row = dataTable.NewRow();
            row["Col1"] = ComboItems2.Item2D.ToString();
            row["Col2"] = "Item Text : " + ComboItems2.Item2D.ToString();
            dataTable.Rows.Add(row);

            row = dataTable.NewRow();
            row["Col1"] = ComboItems2.Item2B.ToString();
            row["Col2"] = "Item Text : " + ComboItems2.Item2B.ToString();
            dataTable.Rows.Add(row);

            row = dataTable.NewRow();
            row["Col1"] = ComboItems2.Item2A.ToString();
            row["Col2"] = "Item Text : " + ComboItems2.Item2A.ToString();
            dataTable.Rows.Add(row);
        }

        dgrid1.ItemsSource = dataTable.DefaultView;
    }
}
AutoGeneratingColumn--保留对DisplayMemberPath和SelectedValuePath的引用,这些引用在前面的一个链接中被引用:

private void dgrid1_AutoGeneratingColumn(object sender, DataGridAutoGeneratingColumnEventArgs e)
{
    if (combo1.SelectedIndex == (int)EnumItems.Item1)
    {
        if (e.PropertyName == "Col1")
        {
            DataGridComboBoxColumn clm = new DataGridComboBoxColumn();
            clm.Header = e.PropertyName;
            clm.ItemsSource = Enum.GetValues(typeof(ComboItems1)).Cast<ComboItems1>();
            //clm.DisplayMemberPath = "Col1";
            //clm.SelectedValuePath = "Col1";

            clm.SelectedValueBinding = new Binding("Col1"); ;

            e.Column = clm;

        }
    }
}
private void dgrid1_AutoGeneratingColumn(对象发送方,DataGridAutoGeneratingColumnEventArgs e)
{
if(combo1.SelectedIndex==(int)EnumItems.Item1)
{
如果(e.PropertyName==“Col1”)
{
DataGridComboxColumn clm=新DataGridComboxColumn();
clm.Header=e.PropertyName;
clm.ItemsSource=Enum.GetValues(typeof(ComboItems1)).Cast();
//clm.DisplayMemberPath=“Col1”;
//clm.SelectedValuePath=“Col1”;
clm.SelectedValueBinding=新绑定(“Col1”);
e、 列=clm;
}
}
}

这只是因为枚举和字符串之间存在类型转换问题。您可以使用TypeConverter或IValueConverter,但就演示而言,最简单的修复方法就是更改:

clm.ItemsSource = Enum.GetValues(typeof(ComboItems1)).Cast<ComboItems1>();

i、 e.因此items集合是一组字符串,而不是枚举,ahich然后正确映射到列类型。

这解决了问题,看起来更好。谢谢关于如何使ComboBox始终可见,而不仅仅是在单元格内单击“编辑条目”时可见,您有什么想法吗?要实现这一点,我认为您必须使用DataGridTemplateColumn和包含ComboBox的模板,而不是DataGridComboBoxColumn。
clm.ItemsSource = Enum.GetValues(typeof(ComboItems1)).Cast<ComboItems1>();
clm.ItemsSource = (from System.Enum v in Enum.GetValues(typeof(ComboItems1)) select v.ToString());