I have a XamDataGrid with table data giving a master detail relationship.
Master (Particle):
Fields: Name, Retention Time, Signals => detail
Detail (Signal):
Fields: Integral, Volume, Concentration…
Now the field integral can have different units thus the header must vary accordingly. As the signals are loaded dynamically and even the user can specify his own type of signals, the header label needs to be created on the fly for each record differently.
How can this be done?
Hello Michal,
sorry I need to add to this thread again....
There is a problem with this solution.
If you open a FieldChooser related to this DataGrid the field using the dynamic label will show blank.
Even if you return a constant string from the Converter class.
Any solution to this problem?
Regards Horst
Hello Michael,
sorry, I need to come back to this thread....
I now have the problem that with such a design if you open a FieeldChooser it will show a blank item for the dynamic Label even if you default to a constant string in the Converter Class.
great, this works exacly as expected!
regards Horst
Hello Horst,
Here is a blog post on changing out the sub field headers.
http://wpfthoughts.blogspot.com/2018/08/xamdatagrid-different-headings-on-child.html
Let me know if you have any questions.
to illustrate better what I mean here the grid with the current layout:
The "Area" field needs to have a varying header label according to the signal.
I am currently setting the grid during an update process caused by some internal state changes:
/// <summary> /// Redisplay if calibrations changed /// </summary> private void Update(object sender, EventArgs e) { Dispatcher.Invoke(() => { RunsTable.DataSource = null; RunsTable.DataSource = Project.CalculationRuns; AttachedResultsGraph.UpdateSeries(); }); }
To update the labels of the "Area" field i am currently using a rather crude work arround:
/// <summary> /// Show/hide signal names depending on run and /// Check if signal requires different area display and create new cloned layout accordingly /// </summary> private void RunsTable_AssigningFieldLayoutToItemDirect(object sender, AssigningFieldLayoutToItemEventArgs e) { Run run = e.Item as Run; if (run != null) { if (run.QuantitativeMultipleSignals) { e.FieldLayout = RunsTable.FieldLayouts["MultipleSignals"]; } else { e.FieldLayout = RunsTable.FieldLayouts["SingleSignal"]; } } Peak peak = e.Item as Peak; if (peak != null) { FieldLayout defaultLayout = RunsTable.FieldLayouts["Peak"]; string areaUnit = "V s"; Trace trace = peak.ParentTrace; if (string.IsNullOrEmpty(trace.AreaUnit) || trace.AreaUnit == areaUnit) { return; } if (trace != null) { areaUnit = trace.AreaUnit; FieldLayout existing = null; foreach (FieldLayout fieldLayout in RunsTable.FieldLayouts) { if (fieldLayout.Key.ToString() == areaUnit) { existing = fieldLayout; break; } } if (existing != null) { e.FieldLayout = existing; } else { FieldLayout layout = new FieldLayout(); layout.Key = areaUnit; foreach (Field field in defaultLayout.Fields) { Field clonedField = null; if (field is TextField) clonedField = new TextField(); if (field is NumericField) clonedField = new NumericField(); clonedField.Name = field.Name; clonedField.Format = field.Format; clonedField.Width = field.Width; clonedField.LabelTextAlignment = field.LabelTextAlignment; clonedField.HorizontalContentAlignment = field.HorizontalContentAlignment; clonedField.AllowEdit = field.AllowEdit; clonedField.AllowSorting = field.AllowSorting; clonedField.Visibility = field.Visibility; clonedField.ToolTip = field.ToolTip; clonedField.Settings.LabelPresenterStyle = field.Settings.LabelPresenterStyle; if (field.Name == "Area") { clonedField.Label = "Area\r[" + areaUnit + "]"; } else { clonedField.Label = field.Label; } layout.Fields.Add(clonedField); } RunsTable.FieldLayouts.Add(layout); e.FieldLayout = layout; } e.Handled = true; } } }
This approach looks for changes in the desired label and clones a new layout if no match found.
I think one can find a more elegant solution.