|
|
|
@ -6,6 +6,9 @@ using System.ComponentModel; |
|
|
|
using System.Windows; |
|
|
|
using System.Windows; |
|
|
|
using System.Windows.Controls; |
|
|
|
using System.Windows.Controls; |
|
|
|
using System.Windows.Data; |
|
|
|
using System.Windows.Data; |
|
|
|
|
|
|
|
using System.Linq; |
|
|
|
|
|
|
|
using MultiTerm.Wpf.CustomControl.ValueConverter; |
|
|
|
|
|
|
|
using System.Diagnostics.Metrics; |
|
|
|
|
|
|
|
|
|
|
|
namespace MultiTerm.Wpf.CustomControl; |
|
|
|
namespace MultiTerm.Wpf.CustomControl; |
|
|
|
|
|
|
|
|
|
|
|
@ -15,7 +18,9 @@ public class MultiFormatDataView : Control |
|
|
|
private const string itemsControlTemplateName = "itemsControl"; |
|
|
|
private const string itemsControlTemplateName = "itemsControl"; |
|
|
|
private const string buttonClearTemplateName = "btnClear"; |
|
|
|
private const string buttonClearTemplateName = "btnClear"; |
|
|
|
private const string selectorTemplateName = "comboBoxSelector"; |
|
|
|
private const string selectorTemplateName = "comboBoxSelector"; |
|
|
|
|
|
|
|
private const string textBoxCharOnlyViewTemplateName = "textBoxCharactersOnlyView"; |
|
|
|
private ListBox? itemsControl; |
|
|
|
private ListBox? itemsControl; |
|
|
|
|
|
|
|
private TextBox? tbCharOnlyView; |
|
|
|
|
|
|
|
|
|
|
|
#region Dependency Properties |
|
|
|
#region Dependency Properties |
|
|
|
public static readonly DependencyProperty DataSourceProperty = |
|
|
|
public static readonly DependencyProperty DataSourceProperty = |
|
|
|
@ -183,22 +188,62 @@ public class MultiFormatDataView : Control |
|
|
|
{ |
|
|
|
{ |
|
|
|
button.Click += OnClearButtonClicked; ; |
|
|
|
button.Click += OnClearButtonClicked; ; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// get textBox from template, ignore if it does not exist |
|
|
|
|
|
|
|
if (GetTemplateChild(textBoxCharOnlyViewTemplateName) is TextBox tb) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
this.tbCharOnlyView = tb; |
|
|
|
|
|
|
|
this.tbCharOnlyView.SelectionChanged += TextBoxCharOnlyView_SelectionChanged; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void OnDataSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|
|
|
private static void OnDataSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// extract instance and guard null |
|
|
|
// extract instance and guard null |
|
|
|
if (d is not MultiFormatDataView mfdv) { return; } |
|
|
|
if (d is not MultiFormatDataView mfdv) { return; } |
|
|
|
// extract instance of new Value and guard null |
|
|
|
|
|
|
|
if (e.NewValue is not IEnumerable enumerable) { return; } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// check if enumerable items are all of correct type |
|
|
|
// extract instance of new Value and check if correct type |
|
|
|
foreach (var item in enumerable) |
|
|
|
if (e.NewValue is not IEnumerable<DataViewModel> newDataSource) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (item is not DataViewModel) |
|
|
|
throw new ArgumentException($"{nameof(MultiFormatDataView)}: {nameof(DataSourceProperty)} must be of type {nameof(IEnumerable<DataViewModel>)}"); |
|
|
|
{ throw new ArgumentException($"{nameof(DataSourceProperty)} must be of type {nameof(DataViewModel)}"); } |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// add group property |
|
|
|
// TODO REMOVE |
|
|
|
|
|
|
|
//// validate that no characters were removed |
|
|
|
|
|
|
|
//if(oldDataSource != null && oldDataSource.Count() > newDataSource.Count()) |
|
|
|
|
|
|
|
//{ |
|
|
|
|
|
|
|
// throw new NotImplementedException($"{nameof(MultiFormatDataView)} cannot handle removing single items from DataSource. " + |
|
|
|
|
|
|
|
// $"Only adding and clearing ({nameof(DataSourceProperty)} = null) are supported."); |
|
|
|
|
|
|
|
//} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//// iterate through data, adding content to textbox |
|
|
|
|
|
|
|
//int prevCounter = newDataSource.First().LineIdentifier; |
|
|
|
|
|
|
|
//for(int i = 0; i < newDataSource.Count(); i++) |
|
|
|
|
|
|
|
//{ |
|
|
|
|
|
|
|
// DataViewModel item = newDataSource.ElementAt(i); |
|
|
|
|
|
|
|
// DataViewModel? oldItem = oldDataSource?.ElementAtOrDefault(i); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // if old item at this position exists and it equals the new item => skip |
|
|
|
|
|
|
|
// if(oldItem != null && oldItem.Equals(item)) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// continue; |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// // new item found: add it as content to textbox |
|
|
|
|
|
|
|
// if (mfdv.tbCharOnlyView != null) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// // newline if previous counter is lower than this |
|
|
|
|
|
|
|
// if (item.LineIdentifier > prevCounter) |
|
|
|
|
|
|
|
// { |
|
|
|
|
|
|
|
// mfdv.tbCharOnlyView.Text += "\n"; |
|
|
|
|
|
|
|
// prevCounter = item.LineIdentifier; |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
// // add character (text) |
|
|
|
|
|
|
|
// mfdv.tbCharOnlyView.Text += item.DisplayStringUtf16; |
|
|
|
|
|
|
|
// } |
|
|
|
|
|
|
|
//} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// add group property to support grouping of VirtualizingWrapPanel |
|
|
|
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(e.NewValue); |
|
|
|
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(e.NewValue); |
|
|
|
PropertyGroupDescription groupDescription = new(nameof(DataViewModel.LineIdentifier)); |
|
|
|
PropertyGroupDescription groupDescription = new(nameof(DataViewModel.LineIdentifier)); |
|
|
|
view.GroupDescriptions.Add(groupDescription); |
|
|
|
view.GroupDescriptions.Add(groupDescription); |
|
|
|
@ -217,6 +262,9 @@ public class MultiFormatDataView : Control |
|
|
|
// if there are no changes => return |
|
|
|
// if there are no changes => return |
|
|
|
if (e.AddedItems.Count <= 0 && e.RemovedItems.Count <= 0) { return; } |
|
|
|
if (e.AddedItems.Count <= 0 && e.RemovedItems.Count <= 0) { return; } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// if there is something selected in the textbox => clear selection first |
|
|
|
|
|
|
|
if (this.tbCharOnlyView != null && this.tbCharOnlyView.SelectionLength > 0) { this.tbCharOnlyView.Select(0, 0); } |
|
|
|
|
|
|
|
|
|
|
|
// otherwise update internal list |
|
|
|
// otherwise update internal list |
|
|
|
foreach (DataViewModel item in e.RemovedItems) |
|
|
|
foreach (DataViewModel item in e.RemovedItems) |
|
|
|
{ |
|
|
|
{ |
|
|
|
@ -228,6 +276,35 @@ public class MultiFormatDataView : Control |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void TextBoxCharOnlyView_SelectionChanged(object sender, RoutedEventArgs e) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
var newSelection = new List<DataViewModel>(); |
|
|
|
|
|
|
|
int selectionStartIndex = this.tbCharOnlyView!.SelectionStart; |
|
|
|
|
|
|
|
// extract text from the beginning to the start of the selected text |
|
|
|
|
|
|
|
var textFromBeginningToStartOfSelection = this.tbCharOnlyView!.Text.Substring(0, selectionStartIndex); |
|
|
|
|
|
|
|
// count amount of manually introduced newline sequences in this text section (these to not exist in the data source!) |
|
|
|
|
|
|
|
var foundManuallyIntroducedNewlineSequences = textFromBeginningToStartOfSelection.Count((x) => x == DataViewModelToStringConverter.NewlineSequence); |
|
|
|
|
|
|
|
// convert datasource |
|
|
|
|
|
|
|
var collection = ((IEnumerable<DataViewModel>)this.DataSource); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// iterate through length of selection |
|
|
|
|
|
|
|
for (int i = 0; i < this.tbCharOnlyView!.SelectionLength; i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
// subtracting the counted newline sequences and adding i (length) |
|
|
|
|
|
|
|
int elementPositionInCollection = selectionStartIndex - foundManuallyIntroducedNewlineSequences + i; |
|
|
|
|
|
|
|
// add element to new selection list |
|
|
|
|
|
|
|
newSelection.Add(collection.ElementAt(elementPositionInCollection)); |
|
|
|
|
|
|
|
// next item does not exist => break loop |
|
|
|
|
|
|
|
if(collection.ElementAtOrDefault(elementPositionInCollection + 1) == null) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
break; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// update property |
|
|
|
|
|
|
|
this.SelectedItems = newSelection; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static void OnSelectedItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|
|
|
private static void OnSelectedItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// NOP |
|
|
|
// NOP |
|
|
|
|