implemented RealizedItemsCount Property for MultiFormatDataView

master
Jonas Arnold 3 years ago
parent 0210de0c2b
commit 02bf114413
  1. 5
      MultiTerm.Wpf.CustomControl/ExtendedTabControl/ExtendedTabControl.cs
  2. 76
      MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.cs
  3. 56
      MultiTerm.Wpf.CustomControl/MultiFormatDataView/MultiFormatDataView.xaml
  4. 41
      MultiTerm.Wpf.CustomControl/UIHelper.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);
}
}

@ -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;
/// <MyNamespace:MultiFormatDataView/>
///
/// </summary>
public class MultiFormatDataView : Control
{
private static readonly Dictionary<StackPanel, MultiFormatDataView> 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));
/// <summary>
/// .NET Property for DataSource.
/// </summary>
@ -58,6 +79,16 @@ public class MultiFormatDataView : Control
set { SetValue(DataSourceProperty, value); }
}
/// <summary>
/// .NET Property for RealizedItemsCount.
/// </summary>
[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<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--;
}
}
}

@ -1,15 +1,46 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<ResourceDictionary x:Class="MultiTerm.Wpf.CustomControl.TemplateStackPanel"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MultiTerm.Wpf.CustomControl"
xmlns:wpftk="clr-namespace:WpfToolkit.Controls;assembly=VirtualizingWrapPanel">
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">
<Style TargetType="{x:Type local:MultiFormatDataView}">
<Style.Resources>
<SolidColorBrush x:Key="CHAR_Background" Color="#B4EBEB"/>
<SolidColorBrush x:Key="HEX_Background" Color="#C8C8FF"/>
<SolidColorBrush x:Key="BIN_Background" Color="#C8FFC8"/>
<DataTemplate x:Key="dataContainerTemplate">
<StackPanel Orientation="Vertical" Margin="0 0 5 0">
<DataTemplate x:Key="dataContainerTemplate" DataType="vm:DataViewModel">
<StackPanel Orientation="Vertical" Margin="0 0 5 0" x:Name="ItemStackPanel">
<StackPanel.Triggers>
<EventTrigger SourceName="ItemStackPanel" RoutedEvent="Loaded">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemStackPanel" Storyboard.TargetProperty="(local:MultiFormatDataView.ItemLoaded)">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<sys:Boolean>True</sys:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger SourceName="ItemStackPanel" RoutedEvent="Unloaded">
<BeginStoryboard>
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ItemStackPanel" Storyboard.TargetProperty="(local:MultiFormatDataView.ItemUnloaded)">
<DiscreteObjectKeyFrame KeyTime="0:0:0">
<DiscreteObjectKeyFrame.Value>
<sys:Boolean>True</sys:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</StackPanel.Triggers>
<!-- Character -->
<Border BorderThickness="0">
<Label Content="{Binding DisplayStringUtf16}">
@ -83,11 +114,15 @@
<ControlTemplate TargetType="{x:Type local:MultiFormatDataView}">
<DockPanel>
<GroupBox Header="Display Formats" DockPanel.Dock="Top">
<StackPanel Orientation="Horizontal" >
<CheckBox Content="Character" x:Name="cbCharacter" Padding="20 0" IsChecked="True"/>
<CheckBox Content="Hexadecimal" x:Name="cbHex" Padding="20 0"/>
<CheckBox Content="Binary" x:Name="cbBin" Padding="20 0"/>
</StackPanel>
<DockPanel LastChildFill="False">
<CheckBox DockPanel.Dock="Left" Content="Character" VerticalAlignment="Center" x:Name="cbCharacter" Padding="20 0" IsChecked="True"/>
<CheckBox DockPanel.Dock="Left" Content="Hexadecimal" VerticalAlignment="Center" x:Name="cbHex" Padding="20 0"/>
<CheckBox DockPanel.Dock="Left" Content="Binary" VerticalAlignment="Center" x:Name="cbBin" Padding="20 0"/>
<StackPanel DockPanel.Dock="Right" Orientation="Horizontal" VerticalAlignment="Center">
<Label Content="Realized Items: " Margin="0 0 5 0"/>
<Label Width="30" Content="{TemplateBinding RealizedItemsCount}"/>
</StackPanel>
</DockPanel>
</GroupBox>
<ListView Name="itemsControl"
ItemsSource="{TemplateBinding DataSource}"
@ -96,6 +131,7 @@
ScrollViewer.PanningMode="VerticalOnly"
HorizontalAlignment="Left"
VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingPanel.CacheLengthUnit="Item"
ItemTemplate="{StaticResource dataContainerTemplate}">
<ListView.ItemContainerStyle>
@ -104,7 +140,7 @@
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<wpftk:VirtualizingWrapPanel

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows;
namespace MultiTerm.Wpf.CustomControl;
public static class UIHelper
{
/// from https://stackoverflow.com/questions/636383/how-can-i-find-wpf-controls-by-name-or-type
/// <summary>
/// Finds a parent of a given item on the visual tree.
/// </summary>
/// <typeparam name="T">The type of the queried item.</typeparam>
/// <param name="child">A direct or indirect child of the queried item.</param>
/// <returns>The first parent item that matches the submitted type parameter.
/// If not matching item can be found, a null reference is being returned.</returns>
public static T? FindVisualParent<T>(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<T>(parentObject);
}
}
}
Loading…
Cancel
Save