|
@@ -52,191 +52,6 @@ using VirtualizingCellsControl = Syncfusion.UI.Xaml.Grid.VirtualizingCellsContro
|
|
|
|
|
|
namespace InABox.DynamicGrid;
|
|
|
|
|
|
-public class DynamicGridRowStyle : DynamicGridStyle<VirtualizingCellsControl>
|
|
|
-{
|
|
|
- public DynamicGridRowStyle() : base(null)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- public DynamicGridRowStyle(IDynamicGridStyle source) : base(source)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- public override DependencyProperty FontSizeProperty => Control.FontSizeProperty;
|
|
|
-
|
|
|
- public override DependencyProperty FontStyleProperty => Control.FontStyleProperty;
|
|
|
-
|
|
|
- public override DependencyProperty FontWeightProperty => Control.FontWeightProperty;
|
|
|
-
|
|
|
- public override DependencyProperty BackgroundProperty => Control.BackgroundProperty;
|
|
|
-
|
|
|
- public override DependencyProperty ForegroundProperty => Control.ForegroundProperty;
|
|
|
-}
|
|
|
-
|
|
|
-public class DynamicGridCellStyle : DynamicGridStyle<Control>
|
|
|
-{
|
|
|
- public DynamicGridCellStyle() : base(null)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- public DynamicGridCellStyle(IDynamicGridStyle source) : base(source)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- public override DependencyProperty FontSizeProperty => Control.FontSizeProperty;
|
|
|
-
|
|
|
- public override DependencyProperty FontStyleProperty => Control.FontStyleProperty;
|
|
|
-
|
|
|
- public override DependencyProperty FontWeightProperty => Control.FontWeightProperty;
|
|
|
-
|
|
|
- public override DependencyProperty BackgroundProperty => Control.BackgroundProperty;
|
|
|
-
|
|
|
- public override DependencyProperty ForegroundProperty => Control.ForegroundProperty;
|
|
|
-}
|
|
|
-
|
|
|
-public class GridSelectionControllerExt : GridSelectionController
|
|
|
-{
|
|
|
- public GridSelectionControllerExt(SfDataGrid datagrid)
|
|
|
- : base(datagrid)
|
|
|
- {
|
|
|
- }
|
|
|
-
|
|
|
- protected override void ProcessSelectedItemChanged(SelectionPropertyChangedHandlerArgs handle)
|
|
|
- {
|
|
|
- base.ProcessSelectedItemChanged(handle);
|
|
|
- if (handle.NewValue != null)
|
|
|
- {
|
|
|
- //this.DataGrid.ScrollInView(this.CurrentCellManager.CurrentRowColumnIndex);
|
|
|
- //int rowIndex = this.CurrentCellManager.CurrentRowColumnIndex.RowIndex;
|
|
|
- var columnIndex = CurrentCellManager.CurrentRowColumnIndex.ColumnIndex;
|
|
|
- var scrollRowIndex = DataGrid.GetVisualContainer().ScrollRows.LastBodyVisibleLineIndex;
|
|
|
- DataGrid.ScrollInView(new RowColumnIndex(scrollRowIndex, columnIndex));
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-public class DynamicGridSummaryStyleSelector : StyleSelector
|
|
|
-{
|
|
|
- private readonly IDynamicGrid _grid;
|
|
|
-
|
|
|
- public DynamicGridSummaryStyleSelector(IDynamicGrid grid)
|
|
|
- {
|
|
|
- _grid = grid;
|
|
|
- }
|
|
|
-
|
|
|
- public override Style SelectStyle(object item, DependencyObject container)
|
|
|
- {
|
|
|
- var vcol = ((GridTableSummaryCell)container).ColumnBase.ColumnIndex;
|
|
|
- var col = vcol > -1 && vcol < _grid.VisibleColumns.Count ? _grid.VisibleColumns[vcol] : null;
|
|
|
-
|
|
|
- var style = new Style(typeof(GridTableSummaryCell));
|
|
|
- style.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.Gainsboro)));
|
|
|
- style.Setters.Add(new Setter(Control.ForegroundProperty, new SolidColorBrush(Colors.Black)));
|
|
|
- style.Setters.Add(new Setter(Control.HorizontalContentAlignmentProperty,
|
|
|
- col != null ? col.HorizontalAlignment(typeof(double)) : HorizontalAlignment.Right));
|
|
|
- style.Setters.Add(new Setter(Control.BorderBrushProperty, new SolidColorBrush(Colors.Gray)));
|
|
|
- style.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(0, 0, 0.75, 0)));
|
|
|
- style.Setters.Add(new Setter(Control.FontSizeProperty, 12D));
|
|
|
- style.Setters.Add(new Setter(Control.FontWeightProperty, FontWeights.DemiBold));
|
|
|
- return style;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-// Used to render boolean columns (the default "false" value shows what appears to be an intermediate state, which is ugly
|
|
|
-// This should show nothing for false, and a tick in a box for true
|
|
|
-public class BoolToImageConverter : AbstractConverter<bool,ImageSource>
|
|
|
-{
|
|
|
-
|
|
|
- public ImageSource TrueValue { get; set; }
|
|
|
- public ImageSource FalseValue { get; set; }
|
|
|
-
|
|
|
- public BoolToImageConverter()
|
|
|
- {
|
|
|
- TrueValue = Wpf.Resources.Bullet_Tick.AsBitmapImage();
|
|
|
- }
|
|
|
-
|
|
|
- public override ImageSource Convert(bool value)
|
|
|
- {
|
|
|
- return value ? TrueValue : FalseValue;
|
|
|
- }
|
|
|
-
|
|
|
- public override bool Deconvert(ImageSource value)
|
|
|
- {
|
|
|
- return ImageUtils.IsEqual(value as BitmapImage,TrueValue as BitmapImage);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-public class StringToColorImageConverter : IValueConverter
|
|
|
-{
|
|
|
- private readonly int _height = 50;
|
|
|
- private readonly int _width = 25;
|
|
|
- private readonly Dictionary<string, BitmapImage> cache = new();
|
|
|
-
|
|
|
- public StringToColorImageConverter(int width, int height)
|
|
|
- {
|
|
|
- _width = width;
|
|
|
- _height = height;
|
|
|
- }
|
|
|
-
|
|
|
- public object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
|
|
- {
|
|
|
- var str = value?.ToString();
|
|
|
- if (str is null)
|
|
|
- return null;
|
|
|
-
|
|
|
- var colorcode = str.TrimStart('#');
|
|
|
-
|
|
|
- if (!cache.ContainsKey(colorcode))
|
|
|
- {
|
|
|
- var col = ImageUtils.StringToColor(colorcode);
|
|
|
- var bmp = ImageUtils.BitmapFromColor(col, _width, _height, Color.Black);
|
|
|
- cache[colorcode] = bmp.AsBitmapImage();
|
|
|
- }
|
|
|
-
|
|
|
- var result = cache[colorcode];
|
|
|
- return result;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
|
|
- {
|
|
|
- return null;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-public class StringArrayConverter : IValueConverter
|
|
|
-{
|
|
|
- object? IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
|
|
- {
|
|
|
- if (value is string[] strArray)
|
|
|
- {
|
|
|
- return string.Join("\n", strArray);
|
|
|
- }
|
|
|
- Logger.Send(LogType.Error, "", $"Attempt to convert an object which is not a string array: {value}.");
|
|
|
- return null;
|
|
|
- }
|
|
|
-
|
|
|
- object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
|
|
- {
|
|
|
- return value;
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-[Serializable]
|
|
|
-class DynamicGridDragFormat
|
|
|
-{
|
|
|
- private string entity;
|
|
|
-
|
|
|
- public DataTable Table { get; set; }
|
|
|
-
|
|
|
- public Type Entity { get => CoreUtils.GetEntity(entity); set => entity = value.EntityName(); }
|
|
|
-
|
|
|
- public DynamicGridDragFormat(DataTable table, Type entity)
|
|
|
- {
|
|
|
- Table = table;
|
|
|
- Entity = entity;
|
|
|
- }
|
|
|
-}
|
|
|
|
|
|
public abstract class DynamicGrid : ContentControl
|
|
|
{
|
|
@@ -261,6 +76,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
}
|
|
|
|
|
|
private IDynamicGridUIComponent<T> UIComponent { get; set; }
|
|
|
+ protected IDynamicGridDataComponent<T> DataComponent { get; set; }
|
|
|
|
|
|
private UIElement? _header;
|
|
|
private readonly Button Add;
|
|
@@ -583,7 +399,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
return !IsSequenced;
|
|
|
}
|
|
|
|
|
|
- T IDynamicGrid<T>.LoadItem(CoreRow row) => LoadItem(row);
|
|
|
+ T IDynamicGrid<T>.LoadItem(CoreRow row) => DataComponent.LoadItem(row);
|
|
|
|
|
|
DynamicGridRowStyleSelector<T> IDynamicGridUIComponentParent<T>.RowStyleSelector => RowStyleSelector;
|
|
|
|
|
@@ -970,7 +786,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
{
|
|
|
OnAfterEditorValueChanged(null, new T[] { obj }, new AfterEditorValueChangedArgs(changedColumn, changes), changes);
|
|
|
|
|
|
- SaveItem(obj);
|
|
|
+ DataComponent.SaveItem(obj);
|
|
|
|
|
|
foreach (var (key, value) in changes)
|
|
|
{
|
|
@@ -1066,14 +882,14 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
{
|
|
|
|
|
|
CoreRow[] rows = Data.Rows.Where(x => x.Index.Equals(row1) || x.Index.Equals(row2)).ToArray();
|
|
|
- var items = LoadItems(rows);
|
|
|
+ var items = DataComponent.LoadItems(rows);
|
|
|
var first = (items.First() as ISequenceable)!;
|
|
|
var last = (items.Last() as ISequenceable)!;
|
|
|
var iBuf1 = first.Sequence;
|
|
|
var iBuf2 = last.Sequence;
|
|
|
first.Sequence = iBuf2;
|
|
|
last.Sequence = iBuf1;
|
|
|
- SaveItems(items);
|
|
|
+ DataComponent.SaveItems(items);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
@@ -1106,8 +922,6 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
|
|
|
#region Refresh / Reload
|
|
|
|
|
|
- protected abstract void Reload(Filters<T> criteria, Columns<T> columns, ref SortOrder<T>? sort, Action<CoreTable?, Exception?> action);
|
|
|
-
|
|
|
public Filter<T>? DefineFilter()
|
|
|
{
|
|
|
if (OnDefineFilter is null)
|
|
@@ -1173,20 +987,10 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
if (sort == null && IsSequenced)
|
|
|
sort = new SortOrder<T>("Sequence");
|
|
|
|
|
|
- Reload(
|
|
|
- criteria
|
|
|
- , columns
|
|
|
- , ref sort
|
|
|
- , (table, exception) =>
|
|
|
- {
|
|
|
- if (exception != null)
|
|
|
- {
|
|
|
- Dispatcher.Invoke(() =>
|
|
|
- {
|
|
|
- MessageWindow.ShowError("Sorry! We couldn't load the data.", exception);
|
|
|
- });
|
|
|
- }
|
|
|
- else if (table is not null)
|
|
|
+ DataComponent.Reload(criteria, columns, sort, result =>
|
|
|
+ {
|
|
|
+ result.DoWith(
|
|
|
+ table =>
|
|
|
{
|
|
|
MasterData = table;
|
|
|
Dispatcher.Invoke(() =>
|
|
@@ -1196,9 +1000,15 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
bRefreshing = false;
|
|
|
IsReady = true;
|
|
|
});
|
|
|
- }
|
|
|
- }
|
|
|
- );
|
|
|
+ },
|
|
|
+ exception =>
|
|
|
+ {
|
|
|
+ Dispatcher.Invoke(() =>
|
|
|
+ {
|
|
|
+ MessageWindow.ShowError("Sorry! We couldn't load the data.", exception);
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
}
|
|
|
else
|
|
|
{
|
|
@@ -1386,35 +1196,11 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
|
|
|
#region Load/Save/Delete
|
|
|
|
|
|
- public virtual T[] LoadItems(CoreRow[] rows)
|
|
|
- {
|
|
|
- var result = new List<T>();
|
|
|
- foreach (var row in rows)
|
|
|
- {
|
|
|
- var index = Data.Rows.IndexOf(row);
|
|
|
- result.Add(LoadItem(row));
|
|
|
- }
|
|
|
-
|
|
|
- return result.ToArray();
|
|
|
- }
|
|
|
-
|
|
|
- public abstract T LoadItem(CoreRow row);
|
|
|
-
|
|
|
- public abstract void SaveItem(T item);
|
|
|
-
|
|
|
- public virtual void SaveItems(T[] items)
|
|
|
- {
|
|
|
- foreach (var item in items)
|
|
|
- SaveItem(item);
|
|
|
- }
|
|
|
-
|
|
|
protected virtual bool CanDeleteItems(params CoreRow[] rows)
|
|
|
{
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
- public abstract void DeleteItems(params CoreRow[] rows);
|
|
|
-
|
|
|
protected virtual void DoDelete()
|
|
|
{
|
|
|
var rows = SelectedRows.ToArray();
|
|
@@ -1424,7 +1210,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
if (MessageBox.Show("Are you sure you wish to delete the selected records?", "Confirm Delete", MessageBoxButton.YesNo) ==
|
|
|
MessageBoxResult.Yes)
|
|
|
{
|
|
|
- DeleteItems(rows);
|
|
|
+ DataComponent.DeleteItems(rows);
|
|
|
SelectedRows = Array.Empty<CoreRow>();
|
|
|
OnChanged?.Invoke(this, EventArgs.Empty);
|
|
|
Refresh(false, true);
|
|
@@ -1464,7 +1250,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
if (IsDirectEditMode() && !OpenEditorOnDirectEdit)
|
|
|
{
|
|
|
var item = CreateItem();
|
|
|
- SaveItem(item);
|
|
|
+ DataComponent.SaveItem(item);
|
|
|
|
|
|
var datarow = Data.NewRow();
|
|
|
ObjectToRow(item, datarow);
|
|
@@ -1591,7 +1377,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
if (items.Length == 1)
|
|
|
editor.UnloadEditorPages(false);
|
|
|
foreach (var item in items)
|
|
|
- SaveItem(item);
|
|
|
+ DataComponent.SaveItem(item);
|
|
|
if (items.Length == 1)
|
|
|
editor.UnloadEditorPages(true);
|
|
|
|
|
@@ -1829,7 +1615,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
{
|
|
|
Stopwatch sw = new Stopwatch();
|
|
|
sw.Start();
|
|
|
- items = LoadItems(rows);
|
|
|
+ items = DataComponent.LoadItems(rows);
|
|
|
//Logger.Send(LogType.Information, "DG:LoadItems", String.Format("Loaded Items: {0}ms", sw.ElapsedMilliseconds));
|
|
|
sw.Stop();
|
|
|
}
|
|
@@ -1862,7 +1648,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
|
|
|
protected virtual IEnumerable<T> LoadDuplicatorItems(CoreRow[] rows)
|
|
|
{
|
|
|
- return LoadItems(rows);
|
|
|
+ return DataComponent.LoadItems(rows);
|
|
|
}
|
|
|
|
|
|
private bool DoDuplicate(Button button, CoreRow[] rows)
|
|
@@ -2000,7 +1786,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
var sequence = currow != null ? currow.Get<T, long>(c => ((ISequenceable)c).Sequence) : 0;
|
|
|
|
|
|
var postrows = Data.Rows.Where(r => !ClipBuffer.Item2.Contains(r) && r.Get<ISequenceable, long>(x => x.Sequence) >= sequence);
|
|
|
- updates.AddRange(LoadItems(postrows.ToArray()));
|
|
|
+ updates.AddRange(DataComponent.LoadItems(postrows.ToArray()));
|
|
|
|
|
|
foreach (var update in updates)
|
|
|
{
|
|
@@ -2011,7 +1797,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
|
|
|
if (updates.Any())
|
|
|
{
|
|
|
- SaveItems(updates.ToArray());
|
|
|
+ DataComponent.SaveItems(updates.ToArray());
|
|
|
Refresh(false, true);
|
|
|
}
|
|
|
}
|
|
@@ -2077,7 +1863,7 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
);
|
|
|
list.OnImportItem += o => { return CustomiseImportItem((T)o); };
|
|
|
list.OnCustomiseImport += (o, args) => { args.FileName = CustomiseImportFileName(args.FileName); };
|
|
|
- list.OnSave += (sender, entity) => SaveItem(entity as T);
|
|
|
+ list.OnSave += (sender, entity) => DataComponent.SaveItem(entity as T);
|
|
|
list.OnLoad += (sender, type, fields, id) => LoadImportKeys(fields);
|
|
|
list.ShowDialog();
|
|
|
Refresh(false, true);
|
|
@@ -2143,35 +1929,35 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
}
|
|
|
|
|
|
var sort = LookupFactory.DefineSort<T>();
|
|
|
- Reload(filters, reloadColumns, ref sort, (data, err) => Dispatcher.Invoke(() =>
|
|
|
+ DataComponent.Reload(filters, reloadColumns, sort, result => Dispatcher.Invoke(() =>
|
|
|
{
|
|
|
- if (data is not null)
|
|
|
- {
|
|
|
- var newData = new CoreTable();
|
|
|
- foreach (var column in columns.Items)
|
|
|
- newData.Columns.Add(new CoreColumn { ColumnName = column.Property, DataType = column.Type });
|
|
|
-
|
|
|
- FilterRows(data, newData, filter: row =>
|
|
|
+ result.DoWith(
|
|
|
+ data =>
|
|
|
{
|
|
|
- foreach(var (_, predicate) in predicates)
|
|
|
+ var newData = new CoreTable();
|
|
|
+ foreach (var column in columns.Items)
|
|
|
+ newData.Columns.Add(new CoreColumn { ColumnName = column.Property, DataType = column.Type });
|
|
|
+
|
|
|
+ FilterRows(data, newData, filter: row =>
|
|
|
{
|
|
|
- if (!predicate(row))
|
|
|
+ foreach (var (_, predicate) in predicates)
|
|
|
{
|
|
|
- return false;
|
|
|
+ if (!predicate(row))
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- return true;
|
|
|
+ return true;
|
|
|
+ });
|
|
|
+
|
|
|
+ var list = new List<Tuple<Type?, CoreTable>>() { new(typeof(T), newData) };
|
|
|
+ list.AddRange(LoadExportTables(filters, otherColumns));
|
|
|
+ DoExportTables(list);
|
|
|
+ },
|
|
|
+ err =>
|
|
|
+ {
|
|
|
+ MessageWindow.ShowError("Error in export", err);
|
|
|
});
|
|
|
-
|
|
|
- var list = new List<Tuple<Type?, CoreTable>>() { new(typeof(T), newData) };
|
|
|
- list.AddRange(LoadExportTables(filters, otherColumns));
|
|
|
- DoExportTables(list);
|
|
|
- }
|
|
|
- else if (err is not null)
|
|
|
- {
|
|
|
- Logger.Send(LogType.Error, "", $"Error in export: {CoreUtils.FormatException(err)}");
|
|
|
- MessageBox.Show(err.Message);
|
|
|
- }
|
|
|
}));
|
|
|
}
|
|
|
|
|
@@ -2382,4 +2168,189 @@ public abstract class DynamicGrid<T> : DynamicGrid, IDynamicGridUIComponentParen
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
+}
|
|
|
+public class DynamicGridRowStyle : DynamicGridStyle<VirtualizingCellsControl>
|
|
|
+{
|
|
|
+ public DynamicGridRowStyle() : base(null)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public DynamicGridRowStyle(IDynamicGridStyle source) : base(source)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public override DependencyProperty FontSizeProperty => Control.FontSizeProperty;
|
|
|
+
|
|
|
+ public override DependencyProperty FontStyleProperty => Control.FontStyleProperty;
|
|
|
+
|
|
|
+ public override DependencyProperty FontWeightProperty => Control.FontWeightProperty;
|
|
|
+
|
|
|
+ public override DependencyProperty BackgroundProperty => Control.BackgroundProperty;
|
|
|
+
|
|
|
+ public override DependencyProperty ForegroundProperty => Control.ForegroundProperty;
|
|
|
+}
|
|
|
+
|
|
|
+public class DynamicGridCellStyle : DynamicGridStyle<Control>
|
|
|
+{
|
|
|
+ public DynamicGridCellStyle() : base(null)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public DynamicGridCellStyle(IDynamicGridStyle source) : base(source)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ public override DependencyProperty FontSizeProperty => Control.FontSizeProperty;
|
|
|
+
|
|
|
+ public override DependencyProperty FontStyleProperty => Control.FontStyleProperty;
|
|
|
+
|
|
|
+ public override DependencyProperty FontWeightProperty => Control.FontWeightProperty;
|
|
|
+
|
|
|
+ public override DependencyProperty BackgroundProperty => Control.BackgroundProperty;
|
|
|
+
|
|
|
+ public override DependencyProperty ForegroundProperty => Control.ForegroundProperty;
|
|
|
+}
|
|
|
+
|
|
|
+public class GridSelectionControllerExt : GridSelectionController
|
|
|
+{
|
|
|
+ public GridSelectionControllerExt(SfDataGrid datagrid)
|
|
|
+ : base(datagrid)
|
|
|
+ {
|
|
|
+ }
|
|
|
+
|
|
|
+ protected override void ProcessSelectedItemChanged(SelectionPropertyChangedHandlerArgs handle)
|
|
|
+ {
|
|
|
+ base.ProcessSelectedItemChanged(handle);
|
|
|
+ if (handle.NewValue != null)
|
|
|
+ {
|
|
|
+ //this.DataGrid.ScrollInView(this.CurrentCellManager.CurrentRowColumnIndex);
|
|
|
+ //int rowIndex = this.CurrentCellManager.CurrentRowColumnIndex.RowIndex;
|
|
|
+ var columnIndex = CurrentCellManager.CurrentRowColumnIndex.ColumnIndex;
|
|
|
+ var scrollRowIndex = DataGrid.GetVisualContainer().ScrollRows.LastBodyVisibleLineIndex;
|
|
|
+ DataGrid.ScrollInView(new RowColumnIndex(scrollRowIndex, columnIndex));
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+public class DynamicGridSummaryStyleSelector : StyleSelector
|
|
|
+{
|
|
|
+ private readonly IDynamicGrid _grid;
|
|
|
+
|
|
|
+ public DynamicGridSummaryStyleSelector(IDynamicGrid grid)
|
|
|
+ {
|
|
|
+ _grid = grid;
|
|
|
+ }
|
|
|
+
|
|
|
+ public override Style SelectStyle(object item, DependencyObject container)
|
|
|
+ {
|
|
|
+ var vcol = ((GridTableSummaryCell)container).ColumnBase.ColumnIndex;
|
|
|
+ var col = vcol > -1 && vcol < _grid.VisibleColumns.Count ? _grid.VisibleColumns[vcol] : null;
|
|
|
+
|
|
|
+ var style = new Style(typeof(GridTableSummaryCell));
|
|
|
+ style.Setters.Add(new Setter(Control.BackgroundProperty, new SolidColorBrush(Colors.Gainsboro)));
|
|
|
+ style.Setters.Add(new Setter(Control.ForegroundProperty, new SolidColorBrush(Colors.Black)));
|
|
|
+ style.Setters.Add(new Setter(Control.HorizontalContentAlignmentProperty,
|
|
|
+ col != null ? col.HorizontalAlignment(typeof(double)) : HorizontalAlignment.Right));
|
|
|
+ style.Setters.Add(new Setter(Control.BorderBrushProperty, new SolidColorBrush(Colors.Gray)));
|
|
|
+ style.Setters.Add(new Setter(Control.BorderThicknessProperty, new Thickness(0, 0, 0.75, 0)));
|
|
|
+ style.Setters.Add(new Setter(Control.FontSizeProperty, 12D));
|
|
|
+ style.Setters.Add(new Setter(Control.FontWeightProperty, FontWeights.DemiBold));
|
|
|
+ return style;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+// Used to render boolean columns (the default "false" value shows what appears to be an intermediate state, which is ugly
|
|
|
+// This should show nothing for false, and a tick in a box for true
|
|
|
+public class BoolToImageConverter : AbstractConverter<bool,ImageSource>
|
|
|
+{
|
|
|
+
|
|
|
+ public ImageSource TrueValue { get; set; }
|
|
|
+ public ImageSource FalseValue { get; set; }
|
|
|
+
|
|
|
+ public BoolToImageConverter()
|
|
|
+ {
|
|
|
+ TrueValue = Wpf.Resources.Bullet_Tick.AsBitmapImage();
|
|
|
+ }
|
|
|
+
|
|
|
+ public override ImageSource Convert(bool value)
|
|
|
+ {
|
|
|
+ return value ? TrueValue : FalseValue;
|
|
|
+ }
|
|
|
+
|
|
|
+ public override bool Deconvert(ImageSource value)
|
|
|
+ {
|
|
|
+ return ImageUtils.IsEqual(value as BitmapImage,TrueValue as BitmapImage);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+public class StringToColorImageConverter : IValueConverter
|
|
|
+{
|
|
|
+ private readonly int _height = 50;
|
|
|
+ private readonly int _width = 25;
|
|
|
+ private readonly Dictionary<string, BitmapImage> cache = new();
|
|
|
+
|
|
|
+ public StringToColorImageConverter(int width, int height)
|
|
|
+ {
|
|
|
+ _width = width;
|
|
|
+ _height = height;
|
|
|
+ }
|
|
|
+
|
|
|
+ public object? Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
|
|
+ {
|
|
|
+ var str = value?.ToString();
|
|
|
+ if (str is null)
|
|
|
+ return null;
|
|
|
+
|
|
|
+ var colorcode = str.TrimStart('#');
|
|
|
+
|
|
|
+ if (!cache.ContainsKey(colorcode))
|
|
|
+ {
|
|
|
+ var col = ImageUtils.StringToColor(colorcode);
|
|
|
+ var bmp = ImageUtils.BitmapFromColor(col, _width, _height, Color.Black);
|
|
|
+ cache[colorcode] = bmp.AsBitmapImage();
|
|
|
+ }
|
|
|
+
|
|
|
+ var result = cache[colorcode];
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public object? ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
|
|
+ {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+public class StringArrayConverter : IValueConverter
|
|
|
+{
|
|
|
+ object? IValueConverter.Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
|
|
+ {
|
|
|
+ if (value is string[] strArray)
|
|
|
+ {
|
|
|
+ return string.Join("\n", strArray);
|
|
|
+ }
|
|
|
+ Logger.Send(LogType.Error, "", $"Attempt to convert an object which is not a string array: {value}.");
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
|
|
+ {
|
|
|
+ return value;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+[Serializable]
|
|
|
+class DynamicGridDragFormat
|
|
|
+{
|
|
|
+ private string entity;
|
|
|
+
|
|
|
+ public DataTable Table { get; set; }
|
|
|
+
|
|
|
+ public Type Entity { get => CoreUtils.GetEntity(entity); set => entity = value.EntityName(); }
|
|
|
+
|
|
|
+ public DynamicGridDragFormat(DataTable table, Type entity)
|
|
|
+ {
|
|
|
+ Table = table;
|
|
|
+ Entity = entity;
|
|
|
+ }
|
|
|
}
|