I am developing a user interface program that I am managing through DataTables. In the main view I need to show a general table with the data, said table must be editable, only that the first two columns must be restricted to be able to choose only the already existing options and, at the same time, the second column is dependent on the first , that is, it should work as follows:
| MAIN COLUMN | DEPENDIENT COLUMN |
|---|---|
| OPTION 1 | SUB OPTION A FROM OPTION 1 |
| OPTION 1 | SUB OPTION B FROM OPTION 1 |
| OPTION 2 | SUB OPTION A FROM OPTION 2 |
| OPTION 2 | SUB OPTION B FROM OPTION 2 |
How do I achieve this operation, limiting the user to choosing the options that I offer?
I should also mention that I need to solve it through methods, since I must use it on different occasions with different data.
I have tried to solve it using a DataGrid and its property DataGridComboBoxColumn that allows using ComboBox in the cells, and thus I manage to limit the user, I have managed to link the two DataGridComboBoxColumn that I have through the SelectionChanged event of the DataGrid, but I have not been able to get each row to act separately, that is, every time I select a row, its cell is linked to the ComboBox of the main column that is selected, but it is also linked to all the other ComboBox from the secondary DataGridComboBoxColumn, so if they do not share the value in the Primary Column of the selected cell, the ComboBoxes become blank.
I think my mistake is in the way I filter my data using LINQ, but I can't find a better way to do it.
So far I have two methods:
Method to add the data to the first DataGridComboBoxColumn:
private DataGridComboBoxColumn ComboBoxColumn(string dbfFileName, int dataColumn, int indexColumn)
{
string columnName = dbfFileName.Replace(".DBF", "");
DataTable table = CreateDataTableFromDbf(dbfFileName);
List<Dictionary<string, string>> items = new List<Dictionary<string, string>>();
foreach (DataRow row in table.Rows)
{
Dictionary<string, string> item = new Dictionary<string, string>
{
{ row[indexColumn].ToString(), row[dataColumn].ToString() }
};
items.Add(item);
}
DataGridComboBoxColumn comboBoxColumn = new DataGridComboBoxColumn();
comboBoxColumn.Header = columnName;
comboBoxColumn.DisplayMemberPath = "Value";
comboBoxColumn.SelectedValuePath = "Key";
comboBoxColumn.ItemsSource = items;
comboBoxColumn.SelectedValueBinding = new Binding(columnName);
return comboBoxColumn;
}
It is a method that uses a Dictionary, it works as it should, but when adding the second column, I need an extra value that is used to do the filtering, so, instead of a Dictionary I used a Tuple :
Method to add the secondary column and link it with the primary column:
private DataGridComboBoxColumn DependentComboBoxColumn(string dbfFileName, int dataColumn, int indexColumn)
{
string columnName = dbfFileName.Replace(".DBF", "");
DataTable table1 = CreateDataTableFromDbf(dbfFileName);
List<Tuple<string, string, string>> items = new List<Tuple<string, string, string>>();
foreach (DataRow row in table1.Rows)
{
Tuple<string, string, string> item = new Tuple<string, string, string>(
row[indexColumn].ToString(),
row[columnName].ToString(),
row[dataColumn].ToString()
);
items.Add(item);
}
DataGridComboBoxColumn comboBoxColumn = new DataGridComboBoxColumn
{
Header = columnName,
DisplayMemberPath = "Item3",
SelectedValuePath = "Item2",
SelectedValueBinding = new Binding(columnName),
ItemsSource = items
};
dataGrid.SelectionChanged += (sender, e) =>
{
if (dataGrid.SelectedIndex >= 0)
{
if (dataGrid.SelectedItem is DataRowView selectedItem)
{
var itemID = selectedItem[indexColumn];
if (itemID != null && !Convert.IsDBNull(itemID))
{
comboBoxColumn.ItemsSource = items.AsEnumerable()
.Where(item => item.Item1 == (string)itemID)
.ToList();
}
else
{
comboBoxColumn.ItemsSource = items;
}
}
}
};
return comboBoxColumn;
}
I really think the key is in the dataGrid.SelectionChanged section, I just haven't been able to figure it out. Does anyone have any clues on how to get what I'm looking for?