My brain is still fighting all this binding stuff, it was never this hard on an IBM System/370 MVS in PL/1!
Any road up, I am trying to do something which I think is simple and obvious and can't untangle all the different bits. I might be tripping over the odd bug as well. Basically, I am trying to write a quick and dirty table maintenance system to set up a Sqlite
database which will be used to drive a phone App. I have a number of tables of the form:
Table Characteristic(_id INT PRIMARY KEY,description CHAR);
These populate a number of other tables, e.g.
Table Symptom (_id int PRIMARY KEY,
characteristic int,
another_code int,
more_codes int,
name char,
description char
);
So I want to maintain symptoms in a DataGrid. I populate the datagrid with a binding to the Symptoms DBSet via a Load(). I populate the lookup combobox columns from the lookup tables also from the DBSets I have loaded and bound.
So I get a Datagrid where the Symptom table has loaded and the lookup comboboxes have loaded too, but I can't figure out how to map the id's (which I have mapped to C# friendly names) to the row value ids and then get the row value ids updated when I select
the description. In my mind, I am confident that the combobox is selecting a lookup row which just happens to display the description and the id will be lurking around, just finding the definition of this thing too baffling with the different syntaxes involved.
Here is the Entity definition
// The Table is there as Sqlite.EF6 seems to use the DBSet name if it is not there
[Table("Symptom")]
public class Symptom
{
[Key]
[Column("_id")] // Mapping from Android convention
public int id { get; set; }
public int characteristic { get; set; }
public string name { get; set; }
public string description { get; set; }
public int frequency { get; set; }
public int location { get; set; }
}
[Table("Characteristic")]
public class Characteristic_List
{
[Key]
[Column("_id")]
public int id { get; set; }
public string description { get; set; }
}
[Table("Frequency")]
public class Frequency_List
{
[Key]
[Column("_id")]
public int id { get; set; }
public string description { get; set; }
}
public class DiagnosticContext : DbContext
{
public DiagnosticContext()
{
Database.SetInitializer<DiagnosticContext>(null);
}
public DbSet<Frequency_List> Frequencies { get; set; }
public DbSet<Characteristic_List> Characteristics { get; set; }
}
public DbSet<Symptom> Symptoms { get; set; }
}
Then for reasons too tedious to explain, I ended up with this approach in the Window code to get things up and running;
public partial class MainWindow : Window
{
private DiagnosticContext context = new DiagnosticContext();
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// Load the ComboboxColumn entries
context.Characteristics.Load();
characteristics.ItemsSource = context.Characteristics.Local;
characteristics.Items.SortDescriptions.Add(new SortDescription("description", ListSortDirection.Ascending));
context.Frequencies.Load();
frequencies.ItemsSource = context.Frequencies.Local;
frequencies.Items.SortDescriptions.Add(new SortDescription("description", ListSortDirection.Ascending));
characteristic_combo_col.ItemsSource = context.Characteristics.Local;
frequency_combo_col.ItemsSource = context.Frequencies.Local;
location_combo_col.ItemsSource = context.Locations.Local;
context.Symptoms.Load();
symptom_grid.ItemsSource = context.Symptoms.Local;
}
protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
{
base.OnClosing(e);
this.context.Dispose();
}
And here is the DataGrid set up:
<TabItem Header="Symptoms"><Grid Background="#FFE5E5E5"><DataGrid x:Name="symptom_grid" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="508" Width="756" AutoGenerateColumns="False" ItemsSource="{Binding}"><DataGrid.Columns><DataGridComboBoxColumn x:Name ="characteristic_combo_col" DisplayMemberPath="description" SelectedItemBinding="{Binding id, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValueBinding="{Binding description, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="120" Header="Characteristic"/><DataGridComboBoxColumn x:Name="frequency_combo_col" DisplayMemberPath="description" SelectedItemBinding="{Binding id, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValueBinding="{Binding description, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="120" Header="Frequency"/><DataGridComboBoxColumn x:Name="location_combo_col" DisplayMemberPath="description" SelectedItemBinding="{Binding id, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" SelectedValueBinding="{Binding description, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="120" Header="Location"/><DataGridTextColumn Binding="{Binding name, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="190" Header="Name"/><DataGridTextColumn Binding="{Binding description, NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Width="190" Header="Description"/></DataGrid.Columns></DataGrid></Grid></TabItem>
You may detect a hint of desperation and randomness in there! Before I added in
NotifyOnTargetUpdated=True, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged
it at least dropped down lists, but with the above although it drops down lists it all gets a bit distressed (like me!) and red exclamation marks are the most it can produce!
So in plain English, I want a data grid with drop down selections to set codes in the target table based on the descriptions of those codes from lookup source tables, and to set the drop down selection based on the code in the first place - data entry 101
in my book!