Skip to content

Commit 320fde8

Browse files
authored
Merge pull request #243 from w-ahmad/feat/clipbaord_binding
feat: Implemented ClipboardContentBinding
2 parents 0f38a3c + 67bd9bc commit 320fde8

3 files changed

Lines changed: 88 additions & 21 deletions

File tree

src/Columns/TableViewBoundColumn.cs

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ namespace WinUI.TableView;
1212
/// </summary>
1313
public abstract class TableViewBoundColumn : TableViewColumn
1414
{
15-
private string? _propertyPath;
1615
private Binding _binding = new();
1716
private Func<object, object?>? _funcCompiledPropertyPath;
1817

@@ -43,14 +42,7 @@ public abstract class TableViewBoundColumn : TableViewColumn
4342
/// <summary>
4443
/// Gets the property path for the binding.
4544
/// </summary>
46-
internal string? PropertyPath
47-
{
48-
get
49-
{
50-
_propertyPath ??= Binding?.Path?.Path;
51-
return _propertyPath;
52-
}
53-
}
45+
internal string? PropertyPath => Binding?.Path?.Path;
5446

5547
/// <summary>
5648
/// Gets or sets the binding for the column.
@@ -62,21 +54,31 @@ public virtual Binding Binding
6254
{
6355
if (_binding != value)
6456
{
65-
_binding = value;
66-
67-
if (_binding is not null)
57+
if (value is not null)
6858
{
69-
_binding.Mode = BindingMode.TwoWay;
59+
value.Mode = BindingMode.TwoWay;
7060

71-
if (_binding.UpdateSourceTrigger == UpdateSourceTrigger.Default)
61+
if (value.UpdateSourceTrigger == UpdateSourceTrigger.Default)
7262
{
73-
_binding.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
63+
value.UpdateSourceTrigger = UpdateSourceTrigger.Explicit;
7464
}
7565
}
66+
67+
_binding = value!;
7668
}
7769
}
7870
}
7971

72+
/// <summary>
73+
/// Gets or sets the data binding used to retrieve cell content when copying to the clipboard.
74+
/// If no explicit clipboard binding is set, the column's <see cref="Binding"/> is returned as a fallback.
75+
/// </summary>
76+
public override Binding? ClipboardContentBinding
77+
{
78+
get => base.ClipboardContentBinding ?? Binding;
79+
set => base.ClipboardContentBinding = value;
80+
}
81+
8082
/// <summary>
8183
/// Handles changes to the ElementStyle property.
8284
/// </summary>

src/Columns/TableViewColumn.cs

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
using Microsoft.UI.Xaml;
2+
using Microsoft.UI.Xaml.Data;
3+
using System;
4+
using WinUI.TableView.Extensions;
25
using SD = WinUI.TableView.SortDirection;
36

47
namespace WinUI.TableView;
@@ -15,6 +18,7 @@ public abstract partial class TableViewColumn : DependencyObject
1518
private SD? _sortDirection;
1619
private bool _isFiltered;
1720
private bool _isFrozen;
21+
private Func<object, object?>? _funcCompiledPropertyPath;
1822

1923
/// <summary>
2024
/// Generates a display element for the cell.
@@ -97,6 +101,34 @@ internal void SetOwningTableView(TableView tableView)
97101
return default;
98102
}
99103

104+
/// <summary>
105+
/// Gets the clipboard content of the cell for the specified data item.
106+
/// </summary>
107+
/// <param name="dataItem">The data item.</param>
108+
/// <returns>The clipboard content of the cell.</returns>
109+
public virtual object? GetClipboardContent(object? dataItem)
110+
{
111+
if (dataItem is null)
112+
return null;
113+
114+
if (_funcCompiledPropertyPath is null && !string.IsNullOrWhiteSpace(ClipboardContentBindingPropertyPath))
115+
_funcCompiledPropertyPath = dataItem.GetFuncCompiledPropertyPath(ClipboardContentBindingPropertyPath!);
116+
117+
if (_funcCompiledPropertyPath is not null)
118+
dataItem = _funcCompiledPropertyPath(dataItem);
119+
120+
if (ClipboardContentBinding?.Converter is not null)
121+
{
122+
dataItem = ClipboardContentBinding.Converter.Convert(
123+
dataItem,
124+
typeof(object),
125+
ClipboardContentBinding.ConverterParameter,
126+
ClipboardContentBinding.ConverterLanguage);
127+
}
128+
129+
return dataItem;
130+
}
131+
100132
/// <summary>
101133
/// Gets or sets the header content of the column.
102134
/// </summary>
@@ -169,7 +201,6 @@ public Style? HeaderStyle
169201
set => SetValue(HeaderStyleProperty, value);
170202
}
171203

172-
173204
/// <summary>
174205
/// Gets or sets the style that is used to render cells in the column.
175206
/// </summary>
@@ -316,6 +347,16 @@ internal set
316347
}
317348
}
318349

350+
/// <summary>
351+
/// Gets or sets the data binding used to retrieve cell content when copying to the clipboard.
352+
/// </summary>
353+
public virtual Binding? ClipboardContentBinding { get; set; }
354+
355+
/// <summary>
356+
/// Gets the property path for the <see cref="ClipboardContentBinding"/>.
357+
/// </summary>
358+
internal string? ClipboardContentBindingPropertyPath => ClipboardContentBinding?.Path?.Path;
359+
319360
/// <summary>
320361
/// Gets the owning TableView for the column.
321362
/// </summary>

src/TableView.cs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ internal void CopyToClipboardInternal(bool includeHeaders)
381381
}
382382

383383
var package = new DataPackage();
384-
package.SetText(GetSelectedContent(includeHeaders));
384+
package.SetText(GetSelectedClipboardContent(includeHeaders));
385385
Clipboard.SetContent(package);
386386
}
387387

@@ -392,6 +392,26 @@ internal void CopyToClipboardInternal(bool includeHeaders)
392392
/// <param name="separator">The character used to separate cell values (default is tab).</param>
393393
/// <returns>A string of selected cell content separated by the specified character.</returns>
394394
public string GetSelectedContent(bool includeHeaders, char separator = '\t')
395+
{
396+
var slots = GetSelectedCellSlots();
397+
398+
return GetCellsContent(slots, includeHeaders, separator);
399+
}
400+
401+
/// <summary>
402+
/// Returns the selected cells' or rows' clipboard content as a string, optionally including headers, with values separated by the given character.
403+
/// </summary>
404+
/// <param name="includeHeaders">Whether to include headers in the output.</param>
405+
/// <param name="separator">The character used to separate cell values (default is tab).</param>
406+
/// <returns>A string of selected cell clipboard content separated by the specified character.</returns>
407+
public string GetSelectedClipboardContent(bool includeHeaders, char separator = '\t')
408+
{
409+
var slots = GetSelectedCellSlots();
410+
411+
return GetCellsContent(slots, includeHeaders, separator, true);
412+
}
413+
414+
private IEnumerable<TableViewCellSlot> GetSelectedCellSlots()
395415
{
396416
var slots = Enumerable.Empty<TableViewCellSlot>();
397417

@@ -409,7 +429,7 @@ public string GetSelectedContent(bool includeHeaders, char separator = '\t')
409429
slots = [CurrentCellSlot.Value];
410430
}
411431

412-
return GetCellsContent(slots, includeHeaders, separator);
432+
return slots;
413433
}
414434

415435
/// <summary>
@@ -450,6 +470,11 @@ public string GetRowsContent(int[] rows, bool includeHeaders, char separator = '
450470
/// <param name="separator">The character used to separate cell values.</param>
451471
/// <returns>A string of specified cell content separated by the specified character.</returns>
452472
public string GetCellsContent(IEnumerable<TableViewCellSlot> slots, bool includeHeaders, char separator = '\t')
473+
{
474+
return GetCellsContent(slots, includeHeaders, separator, false);
475+
}
476+
477+
private string GetCellsContent(IEnumerable<TableViewCellSlot> slots, bool includeHeaders, char separator, bool isClipboardContent)
453478
{
454479
if (!slots.Any())
455480
{
@@ -458,9 +483,7 @@ public string GetCellsContent(IEnumerable<TableViewCellSlot> slots, bool include
458483

459484
var minColumn = slots.Select(x => x.Column).Min();
460485
var maxColumn = slots.Select(x => x.Column).Max();
461-
462486
var stringBuilder = new StringBuilder();
463-
var properties = new Dictionary<string, (PropertyInfo, object?)[]>();
464487

465488
if (includeHeaders)
466489
{
@@ -481,7 +504,8 @@ public string GetCellsContent(IEnumerable<TableViewCellSlot> slots, bool include
481504
continue;
482505
}
483506

484-
stringBuilder.Append($"{column.GetCellContent(item)}{separator}");
507+
var content = isClipboardContent ? column.GetClipboardContent(item) : column.GetCellContent(item);
508+
stringBuilder.Append($"{content}{separator}");
485509
}
486510

487511
stringBuilder.Remove(stringBuilder.Length - 1, 1); // remove extra separator at the end of the line

0 commit comments

Comments
 (0)