Reputation: 319
Using C# WPF, I have a dialog that presents the user w/ a ComboBox of SQL Table names and a DataGrid. When making a selection in the ComboBox, that table's data is retrieved and presented dynamically to the user in the DataGrid. They can then make changes to the contents, delete rows, or add rows and save the changes back to the SQL DB.
For one particular table, I want to make one of the columns a ComboBox of a defined set of values which are currently defined in an enum. For the other tables and the other columns of that particular table, simple text fields are fine.
Using several articles on here I have gotten close to what I am trying to accomplish but I am missing something (probably very simple) that is keeping me from getting to where I want to be. Any help would be appreciated.
I have created a simple sample program to demonstrate what I am trying to accomplish and I am including that code in this post -- namely what I am doing on AutoGenratingColumn to change the desired column to a ComboBox. The articles that I have used to get this far are:
Add combobox to datagrid that is linked to a datable
DataGridTemplateColumns, AutoGenerateColumns=true and binding to a DataTable
For my sample program, I am just loading the data programmatically into the DataTable rather than using a DataAdapter to retrieve the values.
In my sample program, I can display the 2nd column of data and an empty combobox w/ the drop down showing the possible values. However, the initial value is not being displayed and a selected value is not being displayed or accepted.
Sample screenshots are:
Clicking column provides ComboBox:
My MainWindow.xaml file is as follows:
<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>
My Enumerations are:
public enum EnumItems { Item1, Item2 };
public enum ComboItems1 { Item1A, Item1B, Item1C, Item1D };
public enum ComboItems2 { Item2A, Item2B, Item2C, Item2D };
For the sample, I do the following on a SelectionChanged and AutoGeneratingColumn:
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 -- leaving references to DisplayMemberPath and SelectedValuePath which were referenced in one of the previous links:
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;
}
}
}
Upvotes: 1
Views: 3181
Reputation: 1138
This is just because of type conversion issues between enums and strings. You could use a TypeConverter or IValueConverter, but for the purposes of your demo the easiest fix is just to change :
clm.ItemsSource = Enum.GetValues(typeof(ComboItems1)).Cast<ComboItems1>();
to
clm.ItemsSource = (from System.Enum v in Enum.GetValues(typeof(ComboItems1)) select v.ToString());
i.e. so the items collection is a set of strings, not Enums, ahich then maps to the column type correctly.
Upvotes: 1