From 02bf114413fdda3f9df64575ab41f2ec1f16f796 Mon Sep 17 00:00:00 2001 From: Jonas Arnold Date: Fri, 21 Apr 2023 13:35:14 +0200 Subject: [PATCH] implemented RealizedItemsCount Property for MultiFormatDataView --- .../ExtendedTabControl/ExtendedTabControl.cs | 5 +- .../MultiFormatDataView.cs | 76 ++++++++++++++++++- .../MultiFormatDataView.xaml | 56 +++++++++++--- MultiTerm.Wpf.CustomControl/UIHelper.cs | 41 ++++++++++ 4 files changed, 164 insertions(+), 14 deletions(-) create mode 100644 MultiTerm.Wpf.CustomControl/UIHelper.cs diff --git a/MultiTerm.Wpf.CustomControl/ExtendedTabControl/ExtendedTabControl.cs b/MultiTerm.Wpf.CustomControl/ExtendedTabControl/ExtendedTabControl.cs index 80e327e..7eba2fb 100644 --- a/MultiTerm.Wpf.CustomControl/ExtendedTabControl/ExtendedTabControl.cs +++ b/MultiTerm.Wpf.CustomControl/ExtendedTabControl/ExtendedTabControl.cs @@ -61,8 +61,7 @@ public class ExtendedTabControl : TabControl base.OnApplyTemplate(); // get button from template - var button = GetTemplateChild("addButton") as Button; - if (button != null) + if (GetTemplateChild("addButton") is Button button) { button.Click += OnAddButtonClicked; ; } @@ -70,7 +69,7 @@ public class ExtendedTabControl : TabControl private void OnAddButtonClicked(object sender, RoutedEventArgs e) { - RoutedEventArgs args = new RoutedEventArgs(AddButtonClickedEvent); + RoutedEventArgs args = new(AddButtonClickedEvent); RaiseEvent(args); } } diff --git a/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.cs b/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.cs index 922bb69..cd46533 100644 --- a/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.cs +++ b/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.cs @@ -1,10 +1,12 @@ 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; +using System.Windows.Threading; namespace MultiTerm.Wpf.CustomControl; @@ -37,8 +39,10 @@ namespace MultiTerm.Wpf.CustomControl; /// /// /// + public class MultiFormatDataView : Control { + private static readonly Dictionary itemParentPairs = new(); private const string itemsControlTemplateName = "itemsControl"; private ItemsControl? itemsControl; @@ -48,6 +52,23 @@ public class MultiFormatDataView : Control typeof(IEnumerable), typeof(MultiFormatDataView), new PropertyMetadata(null, OnDataSourcePropertyChanged)); + 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)); + /// /// .NET Property for DataSource. /// @@ -58,6 +79,16 @@ public class MultiFormatDataView : Control set { SetValue(DataSourceProperty, value); } } + /// + /// .NET Property for RealizedItemsCount. + /// + [Bindable(true)] + public uint RealizedItemsCount + { + get { return (uint)GetValue(RealizedItemsCountProperty); } + set { SetValue(RealizedItemsCountProperty, value); } + } + #endregion static MultiFormatDataView() @@ -65,6 +96,7 @@ public class MultiFormatDataView : Control DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiFormatDataView), new FrameworkPropertyMetadata(typeof(MultiFormatDataView))); } + public override void OnApplyTemplate() { base.OnApplyTemplate(); @@ -78,7 +110,6 @@ public class MultiFormatDataView : Control { throw new Exception($"Implementation fault, {itemsControlTemplateName} not found in template."); } - } private static void OnDataSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) @@ -100,4 +131,47 @@ public class MultiFormatDataView : Control PropertyGroupDescription groupDescription = new(nameof(DataViewModel.LineIdentifier)); view.GroupDescriptions.Add(groupDescription); } + + + 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(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--; + } + } } diff --git a/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.xaml b/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.xaml index d597051..cc9ca43 100644 --- a/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.xaml +++ b/MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.xaml @@ -1,15 +1,46 @@ - + xmlns:vm="clr-namespace:MultiTerm.Core.ViewModel;assembly=MultiTerm.Core" + xmlns:wpftk="clr-namespace:WpfToolkit.Controls;assembly=VirtualizingWrapPanel" + xmlns:sys="clr-namespace:System;assembly=mscorlib"> - + + /// Finds a parent of a given item on the visual tree. + /// + /// The type of the queried item. + /// A direct or indirect child of the queried item. + /// The first parent item that matches the submitted type parameter. + /// If not matching item can be found, a null reference is being returned. + public static T? FindVisualParent(DependencyObject child) + where T : DependencyObject + { + // get parent item + DependencyObject parentObject = VisualTreeHelper.GetParent(child); + + // we’ve reached the end of the tree + if (parentObject == null) return null; + + // check if the parent matches the type we’re looking for + if (parentObject is T parent) + { + return parent; + } + else + { + // use recursion to proceed with next level + return FindVisualParent(parentObject); + } + } +}