|
@@ -19,6 +19,7 @@ using System.Windows.Controls;
|
|
|
using System.Windows.Data;
|
|
|
using System.Windows.Input;
|
|
|
using System.Windows.Media;
|
|
|
+using System.Windows.Media.Imaging;
|
|
|
|
|
|
namespace InABox.DynamicGrid;
|
|
|
|
|
@@ -53,8 +54,6 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
private SfTreeGrid _tree;
|
|
|
private readonly ContextMenu ColumnsMenu;
|
|
|
|
|
|
- private Dictionary<Guid, CoreRow>? _rowMap;
|
|
|
-
|
|
|
public event OnContextMenuOpening OnContextMenuOpening;
|
|
|
|
|
|
FrameworkElement IDynamicGridUIComponent<T>.Control => _tree;
|
|
@@ -129,12 +128,15 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
_tree.AutoExpandMode = AutoExpandMode.AllNodesExpanded;
|
|
|
//_tree.NodeCollapsing += (o, e) => { e.Cancel = true; };
|
|
|
//_tree.HeaderRowHeight = 0D;
|
|
|
+ _tree.HeaderRowHeight = 30;
|
|
|
_tree.HeaderContextMenu = ColumnsMenu;
|
|
|
|
|
|
_tree.SelectionChanging += _tree_SelectionChanging;
|
|
|
_tree.SelectionChanged += _tree_SelectionChanged;
|
|
|
_tree.AllowSelectionOnExpanderClick = false;
|
|
|
|
|
|
+ _tree.AllowAutoSizingExpanderColumn = false;
|
|
|
+
|
|
|
_tree.CellTapped += _tree_CellTapped;
|
|
|
_tree.CellDoubleTapped += _tree_CellDoubleTapped;
|
|
|
_tree.KeyUp += _tree_KeyUp;
|
|
@@ -160,10 +162,24 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
_tree.SelectionForeground = DynamicGridUtils.SelectionForeground;
|
|
|
_tree.SelectionBackground = DynamicGridUtils.SelectionBackground;
|
|
|
|
|
|
- _tree.ColumnSizer = TreeColumnSizer.Star;
|
|
|
+ _tree.ColumnSizer = TreeColumnSizer.None;
|
|
|
_tree.RowHeight = 30D;
|
|
|
_tree.SetValue(Grid.RowProperty, 0);
|
|
|
|
|
|
+ _tree.AllowDraggingRows = false;
|
|
|
+ _tree.Drop += _tree_Drop;
|
|
|
+ _tree.DragOver += _tree_DragOver;
|
|
|
+ _tree.RowDragDropTemplate = TemplateGenerator.CreateDataTemplate(() =>
|
|
|
+ {
|
|
|
+ var border = new Border();
|
|
|
+ border.Width = 100;
|
|
|
+ border.Height = 100;
|
|
|
+ border.BorderBrush = new SolidColorBrush(Colors.Firebrick);
|
|
|
+ border.Background = new SolidColorBrush(Colors.Red);
|
|
|
+ border.CornerRadius = new CornerRadius(5);
|
|
|
+ return border;
|
|
|
+ });
|
|
|
+
|
|
|
_tree.SizeChanged += _tree_SizeChanged;
|
|
|
}
|
|
|
|
|
@@ -171,7 +187,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
public IEnumerable<CoreRow> GetChildren(Guid id)
|
|
|
{
|
|
|
- return Nodes.GetChildren(id).Select(x => x.Row);
|
|
|
+ return Nodes.GetChildren(id).Select(x => MapRow(x.Row));
|
|
|
}
|
|
|
|
|
|
#endregion
|
|
@@ -183,7 +199,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
// Syncfusion has given us the row index, so it also will give us the correct row, after sorting.
|
|
|
// Hence, here we use the syncfusion DataGrid.GetRecordAtRowIndex, which *should* always return a DataRowView.
|
|
|
var row = _tree.GetNodeAtRowIndex(rowIndex);
|
|
|
- return (row.Item as CoreTreeNode)?.Row;
|
|
|
+ return MapRow((row.Item as CoreTreeNode)?.Row);
|
|
|
}
|
|
|
|
|
|
private void _tree_CellDoubleTapped(object? sender, TreeGridCellDoubleTappedEventArgs e)
|
|
@@ -191,7 +207,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
_tree.Dispatcher.BeginInvoke(() =>
|
|
|
{
|
|
|
// This needs to happen outside the event handler, because the items source for the tree view might change during this method, and that causes an internal exception in Syncfusion. We need to finish the event before resetting the items source.
|
|
|
- Parent.DoubleClickCell(GetRowFromIndex(e.RowColumnIndex.RowIndex), GetColumn(e.RowColumnIndex.ColumnIndex));
|
|
|
+ Parent.DoubleClickCell(GetRowFromIndex(e.RowColumnIndex.RowIndex), GetColumn(e.RowColumnIndex.ColumnIndex));
|
|
|
});
|
|
|
}
|
|
|
|
|
@@ -319,7 +335,17 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
private CoreRow? GetRow(CoreTreeNode? node)
|
|
|
{
|
|
|
- return node is not null ? _rowMap?.GetValueOrDefault(node.ID) : null;
|
|
|
+ return MapRow(node?.Row);
|
|
|
+ }
|
|
|
+
|
|
|
+ private CoreRow? MapRow(CoreRow? row)
|
|
|
+ {
|
|
|
+ if (row is null) return null;
|
|
|
+
|
|
|
+ var index = row.Index;
|
|
|
+ if (index < 0 || index >= Parent.Data.Rows.Count) return null;
|
|
|
+
|
|
|
+ return Parent.Data.Rows[row.Index];
|
|
|
}
|
|
|
|
|
|
private void ColumnsMenu_ContextMenuOpening(object sender, RoutedEventArgs e)
|
|
@@ -333,6 +359,29 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
public bool OptionsChanged()
|
|
|
{
|
|
|
ColumnsMenu.Visibility = Parent.HasOption(DynamicGridOption.SelectColumns) ? Visibility.Visible : Visibility.Hidden;
|
|
|
+
|
|
|
+ _tree.AllowFiltering = Parent.HasOption(DynamicGridOption.FilterRows);
|
|
|
+
|
|
|
+ if (Parent.HasOption(DynamicGridOption.DragSource))
|
|
|
+ {
|
|
|
+ if (!_tree.AllowDraggingRows)
|
|
|
+ {
|
|
|
+ _tree.AllowDraggingRows = true;
|
|
|
+ _tree.RowDragDropController.DragStart += RowDragDropController_DragStart;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ if (_tree.AllowDraggingRows)
|
|
|
+ {
|
|
|
+ _tree.AllowDraggingRows = false;
|
|
|
+ _tree.RowDragDropController.DragStart -= RowDragDropController_DragStart;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ _tree.AllowDrop = Parent.HasOption(DynamicGridOption.DragTarget);
|
|
|
+ _tree.SelectionMode = Parent.HasOption(DynamicGridOption.MultiSelect) ? GridSelectionMode.Extended : GridSelectionMode.Single;
|
|
|
+
|
|
|
return false;
|
|
|
}
|
|
|
|
|
@@ -489,7 +538,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
var column = ActionColumns[i];
|
|
|
if (column.Position == position)
|
|
|
{
|
|
|
- var sColName = string.Format("ActionColumn{0}", i);
|
|
|
+ var sColName = $"[_ActionColumn{i}]";
|
|
|
|
|
|
if (column is DynamicImageColumn imgcol)
|
|
|
{
|
|
@@ -502,7 +551,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
Width = _tree.RowHeight - 8,
|
|
|
Height = _tree.RowHeight - 8,
|
|
|
};
|
|
|
- image.SetBinding(Image.SourceProperty, new Binding(sColName) { Converter = new BytesToBitmapImageConverter() });
|
|
|
+ image.SetBinding(Image.SourceProperty, new Binding(sColName));
|
|
|
return image;
|
|
|
} };
|
|
|
|
|
@@ -536,7 +585,7 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
var image = imgcol.Image?.Invoke(null);
|
|
|
if (image != null)
|
|
|
{
|
|
|
- var template = new ControlTemplate(typeof(TreeGridHeaderCell));
|
|
|
+ var template = new DataTemplate(typeof(TreeGridHeaderCell));
|
|
|
var border = new FrameworkElementFactory(typeof(Border));
|
|
|
border.SetValue(Border.BackgroundProperty, new SolidColorBrush(Colors.Gainsboro));
|
|
|
border.SetValue(Border.PaddingProperty, new Thickness(4));
|
|
@@ -545,7 +594,8 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
img.SetValue(Image.SourceProperty, image);
|
|
|
border.AppendChild(img);
|
|
|
template.VisualTree = border;
|
|
|
- headstyle.Setters.Add(new Setter(Control.TemplateProperty, template));
|
|
|
+ headstyle.Setters.Add(new Setter(TreeGridHeaderCell.PaddingProperty, new Thickness(0)));
|
|
|
+ headstyle.Setters.Add(new Setter(TreeGridHeaderCell.ContentTemplateProperty, template));
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -708,19 +758,13 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
ActionColumns = actionColumns.ToList();
|
|
|
|
|
|
- _tree.Columns.Add(new TreeGridTextColumn()
|
|
|
- {
|
|
|
- MappingName = "Description"
|
|
|
- }
|
|
|
- );
|
|
|
-
|
|
|
- _tree.Columns.Add(new TreeGridTextColumn()
|
|
|
- {
|
|
|
- MappingName = "Number",
|
|
|
- Width = _shownumbers ? 50 : 0,
|
|
|
- TextAlignment = TextAlignment.Right
|
|
|
- }
|
|
|
- );
|
|
|
+ //_tree.Columns.Add(new TreeGridTextColumn()
|
|
|
+ // {
|
|
|
+ // MappingName = "Number",
|
|
|
+ // Width = _shownumbers ? 50 : 0,
|
|
|
+ // TextAlignment = TextAlignment.Right
|
|
|
+ // }
|
|
|
+ //);
|
|
|
|
|
|
LoadActionColumns(DynamicActionColumnPosition.Start);
|
|
|
LoadDataColumns(columns);
|
|
@@ -764,6 +808,8 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
public CoreTreeNodes Nodes { get; set; }
|
|
|
|
|
|
+ private CoreTable? _innerTable;
|
|
|
+
|
|
|
public void BeforeRefresh()
|
|
|
{
|
|
|
_tree.SelectionForeground = DynamicGridUtils.SelectionForeground;
|
|
@@ -773,12 +819,37 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
public void RefreshData(CoreTable data)
|
|
|
{
|
|
|
var nodes = new CoreTreeNodes();
|
|
|
+
|
|
|
+ _innerTable = new CoreTable();
|
|
|
+ _innerTable.LoadColumns(data.Columns);
|
|
|
+
|
|
|
+ for (var i = 0; i < ActionColumns.Count; i++)
|
|
|
+ _innerTable.Columns.Add(
|
|
|
+ new CoreColumn
|
|
|
+ {
|
|
|
+ ColumnName = $"_ActionColumn{i}",
|
|
|
+ DataType = ActionColumns[i] is DynamicImageColumn
|
|
|
+ ? typeof(BitmapImage)
|
|
|
+ : typeof(String)
|
|
|
+ });
|
|
|
+
|
|
|
foreach (var row in data.Rows)
|
|
|
{
|
|
|
+ var newRow = _innerTable.NewRow();
|
|
|
+ newRow.LoadValues(row.Values);
|
|
|
+
|
|
|
+ for (var i = 0; i < ActionColumns.Count; i++)
|
|
|
+ {
|
|
|
+ var ac = ActionColumns[i];
|
|
|
+ newRow[$"_ActionColumn{i}"] = ac.Data(row);
|
|
|
+ }
|
|
|
+
|
|
|
+ _innerTable.Rows.Add(newRow);
|
|
|
+
|
|
|
var _id = row.Get<Guid>(IDColumn.Property);
|
|
|
var _parent = row.Get<Guid>(ParentColumn.Property);
|
|
|
var _description = row.Get<string>(DescriptionColumn.Property);
|
|
|
- nodes.Add(_id, _parent, row).Description = _description;
|
|
|
+ nodes.Add(_id, _parent, newRow).Description = _description;
|
|
|
}
|
|
|
Nodes = nodes;
|
|
|
_tree.ItemsSource = nodes.Nodes;
|
|
@@ -838,19 +909,18 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
|
|
|
public CoreRow[] GetVisibleRows()
|
|
|
{
|
|
|
- return _tree.View.Nodes.Select(x => (x.Item as CoreTreeNode)?.Row).NotNull().ToArray();
|
|
|
+ return _tree.View.Nodes.Select(x => MapRow((x.Item as CoreTreeNode)?.Row)).NotNull().ToArray();
|
|
|
}
|
|
|
|
|
|
public void InvalidateRow(CoreRow row)
|
|
|
{
|
|
|
- var rowdata = new List<object?>(row.Values);
|
|
|
- foreach (var ac in ActionColumns)
|
|
|
- rowdata.Add(ac.Data(row));
|
|
|
+ if (_innerTable is null || row.Index < 0 || row.Index >= _innerTable.Rows.Count) return;
|
|
|
|
|
|
- var coreTreeNode = Nodes.Find(row);
|
|
|
+ var _innerRow = _innerTable.Rows[row.Index];
|
|
|
+ var coreTreeNode = Nodes.Find(_innerRow);
|
|
|
if(coreTreeNode is not null)
|
|
|
{
|
|
|
- coreTreeNode.Row = row;;
|
|
|
+ coreTreeNode.InvalidateData();
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -869,4 +939,24 @@ public class DynamicGridTreeUIComponent<T> : IDynamicGridUIComponent<T>, IDynami
|
|
|
{
|
|
|
throw new NotImplementedException();
|
|
|
}
|
|
|
+
|
|
|
+ #region Drag + Drop
|
|
|
+
|
|
|
+ private void _tree_DragOver(object sender, DragEventArgs e)
|
|
|
+ {
|
|
|
+ Parent.DragOver(sender, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void _tree_Drop(object sender, DragEventArgs e)
|
|
|
+ {
|
|
|
+ Parent.Drop(sender, e);
|
|
|
+ }
|
|
|
+
|
|
|
+ private void RowDragDropController_DragStart(object? sender, TreeGridRowDragStartEventArgs e)
|
|
|
+ {
|
|
|
+ var rows = e.DraggingNodes.Select(node => MapRow((node.Item as CoreTreeNode)?.Row)).NotNull().ToArray();
|
|
|
+ Parent.DragStart(sender, rows);
|
|
|
+ }
|
|
|
+
|
|
|
+ #endregion
|
|
|
}
|