Multiprocotol Terminalprogram (BAT)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

238 lines
8.1 KiB

using MultiTerm.Core.ViewModel;
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
namespace MultiTerm.Wpf.CustomControl;
public class MultiFormatDataView : Control
{
private static readonly Dictionary<StackPanel, MultiFormatDataView> itemParentPairs = new();
private const string itemsControlTemplateName = "itemsControl";
private const string buttonClearTemplateName = "btnClear";
private ListBox? itemsControl;
private List<DataViewModel> currentSelectedItems = new();
#region Dependency Properties
public static readonly DependencyProperty DataSourceProperty =
DependencyProperty.Register("DataSource",
typeof(IEnumerable), typeof(MultiFormatDataView),
new PropertyMetadata(null, OnDataSourcePropertyChanged));
public static readonly DependencyProperty SelectedItemsProperty =
DependencyProperty.Register("SelectedItems",
typeof(IList), typeof(MultiFormatDataView),
new FrameworkPropertyMetadata(OnSelectedItemsPropertyChanged)
{
BindsTwoWayByDefault = false
});
public static readonly DependencyProperty RealizedItemsCountProperty =
DependencyProperty.Register("RealizedItemsCount",
typeof(uint), typeof(MultiFormatDataView),
new PropertyMetadata((uint)0, OnRealizedItemsCountChanged));
public static readonly DependencyProperty ItemLoadedProperty =
DependencyProperty.RegisterAttached("ItemLoaded",
typeof(bool),
typeof(MultiFormatDataView),
new UIPropertyMetadata(false, OnItemLoaded));
public static readonly DependencyProperty ItemUnloadedProperty =
DependencyProperty.RegisterAttached("ItemUnloaded",
typeof(bool),
typeof(MultiFormatDataView),
new UIPropertyMetadata(false, OnItemUnloaded));
public static readonly RoutedEvent ClearRequestedEvent;
/// <summary>
/// .NET Property for DataSource.
/// </summary>
[Bindable(true)]
public IEnumerable DataSource
{
get { return (IEnumerable)GetValue(DataSourceProperty); }
set { SetValue(DataSourceProperty, value); }
}
/// <summary>
/// .NET Property for SelectedItems.
/// </summary>
[Bindable(true)]
public IList SelectedItems
{
get { return (IList)GetValue(SelectedItemsProperty); }
set { SetValue(SelectedItemsProperty, value); }
}
/// <summary>
/// .NET Property for RealizedItemsCount.
/// </summary>
[Bindable(true)]
public uint RealizedItemsCount
{
get { return (uint)GetValue(RealizedItemsCountProperty); }
set { SetValue(RealizedItemsCountProperty, value); }
}
/// <summary>
/// .NET Property for ItemLoaded.
/// </summary>
public bool ItemLoaded
{
get { return (bool)GetValue(ItemLoadedProperty); }
set { SetValue(ItemLoadedProperty, value); }
}
/// <summary>
/// .NET Property for ItemUnloaded.
/// </summary>
public bool ItemUnloaded
{
get { return (bool)GetValue(ItemUnloadedProperty); }
set { SetValue(ItemUnloadedProperty, value); }
}
/// <summary>
/// .NET Property for <see cref="ClearRequestedEvent"/>
/// </summary>
public event RoutedEventHandler ClearRequested
{
add { this.AddHandler(ClearRequestedEvent, value); }
remove { this.RemoveHandler(ClearRequestedEvent, value); }
}
#endregion
static MultiFormatDataView()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiFormatDataView), new FrameworkPropertyMetadata(typeof(MultiFormatDataView)));
ClearRequestedEvent = EventManager.RegisterRoutedEvent("ClearRequested",
RoutingStrategy.Bubble, typeof(RoutedEventArgs),
typeof(MultiFormatDataView));
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
this.SelectedItems = new List<DataViewModel>();
// get itemsControl from template
if (GetTemplateChild(itemsControlTemplateName) is ListBox listBox)
{
this.itemsControl = listBox;
this.itemsControl.SelectionChanged += ItemsControl_SelectionChanged;
}
else
{
throw new Exception($"Implementation fault, {itemsControlTemplateName} not found in template.");
}
// get button from template, ignore if it does not exist
if (GetTemplateChild(buttonClearTemplateName) is Button button)
{
button.Click += OnClearButtonClicked; ;
}
}
private static void OnDataSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// extract instance and guard null
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
foreach (var item in enumerable)
{
if (item is not DataViewModel)
{ throw new ArgumentException($"{nameof(DataSourceProperty)} must be of type {nameof(DataViewModel)}"); }
}
// add group property
CollectionView view = (CollectionView)CollectionViewSource.GetDefaultView(e.NewValue);
PropertyGroupDescription groupDescription = new(nameof(DataViewModel.LineIdentifier));
view.GroupDescriptions.Add(groupDescription);
}
private void OnClearButtonClicked(object sender, RoutedEventArgs e)
{
// raise clear requested event
RoutedEventArgs args = new(ClearRequestedEvent);
RaiseEvent(args);
}
#region Selected Items handling
private void ItemsControl_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if(this.currentSelectedItems == null)
{ this.currentSelectedItems = new List<DataViewModel>(); }
// if there are no changes => return
if (e.AddedItems.Count <= 0 && e.RemovedItems.Count <= 0) { return; }
// otherwise update internal list
foreach (DataViewModel item in e.RemovedItems)
{
this.SelectedItems.Remove(item);
}
foreach (DataViewModel item in e.AddedItems)
{
this.SelectedItems.Add(item);
}
}
private static void OnSelectedItemsPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// NOP
}
#endregion
#region Realized Item Count
private static void OnRealizedItemsCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// NOP
}
private static void OnItemLoaded(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// extract instance and guard null
if (d is not StackPanel stackPanel) { return; }
// check if value was set to true
if (e.NewValue is bool boolean && boolean == true)
{
// find visual parent of correct type, throw exception if not found
var parentMFDV = UIHelper.FindVisualParent<MultiFormatDataView>(stackPanel) ??
throw new NullReferenceException($"Could not find parent of type " +
$"{nameof(MultiFormatDataView)} in {nameof(stackPanel)}");
// add to static dictionary
itemParentPairs.Add(stackPanel, parentMFDV);
// increment counter
parentMFDV.RealizedItemsCount++;
}
}
private static void OnItemUnloaded(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// extract instance and guard null
if (d is not StackPanel stackPanel) { return; }
// check if value was set to true
if (e.NewValue is bool boolean && boolean == true)
{
// get parent from static dictionary
var parentMFDV = itemParentPairs[stackPanel];
// remove the element from the dictionary
itemParentPairs.Remove(stackPanel);
// decrement counter
parentMFDV.RealizedItemsCount--;
}
}
#endregion
}