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(); base.OnApplyTemplate();
// get button from template // get button from template
var button = GetTemplateChild("addButton") as Button; if (GetTemplateChild("addButton") is Button button)
if (button != null)
{ {
button.Click += OnAddButtonClicked; ; button.Click += OnAddButtonClicked; ;
} }
@ -70,7 +69,7 @@ public class ExtendedTabControl : TabControl
private void OnAddButtonClicked(object sender, RoutedEventArgs e) private void OnAddButtonClicked(object sender, RoutedEventArgs e)
{ {
RoutedEventArgs args = new RoutedEventArgs(AddButtonClickedEvent); RoutedEventArgs args = new(AddButtonClickedEvent);
RaiseEvent(args); RaiseEvent(args);
} }
} }

@ -1,10 +1,12 @@
using MultiTerm.Core.ViewModel; using MultiTerm.Core.ViewModel;
using System; using System;
using System.Collections; using System.Collections;
using System.Collections.Generic;
using System.ComponentModel; 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.Windows.Threading;
namespace MultiTerm.Wpf.CustomControl; namespace MultiTerm.Wpf.CustomControl;
@ -37,8 +39,10 @@ namespace MultiTerm.Wpf.CustomControl;
/// <MyNamespace:MultiFormatDataView/> /// <MyNamespace:MultiFormatDataView/>
/// ///
/// </summary> /// </summary>
public class MultiFormatDataView : Control public class MultiFormatDataView : Control
{ {
private static readonly Dictionary<StackPanel, MultiFormatDataView> itemParentPairs = new();
private const string itemsControlTemplateName = "itemsControl"; private const string itemsControlTemplateName = "itemsControl";
private ItemsControl? itemsControl; private ItemsControl? itemsControl;
@ -48,6 +52,23 @@ public class MultiFormatDataView : Control
typeof(IEnumerable), typeof(MultiFormatDataView), typeof(IEnumerable), typeof(MultiFormatDataView),
new PropertyMetadata(null, OnDataSourcePropertyChanged)); 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> /// <summary>
/// .NET Property for DataSource. /// .NET Property for DataSource.
/// </summary> /// </summary>
@ -58,6 +79,16 @@ public class MultiFormatDataView : Control
set { SetValue(DataSourceProperty, value); } 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 #endregion
static MultiFormatDataView() static MultiFormatDataView()
@ -65,6 +96,7 @@ public class MultiFormatDataView : Control
DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiFormatDataView), new FrameworkPropertyMetadata(typeof(MultiFormatDataView))); DefaultStyleKeyProperty.OverrideMetadata(typeof(MultiFormatDataView), new FrameworkPropertyMetadata(typeof(MultiFormatDataView)));
} }
public override void OnApplyTemplate() public override void OnApplyTemplate()
{ {
base.OnApplyTemplate(); base.OnApplyTemplate();
@ -78,7 +110,6 @@ public class MultiFormatDataView : Control
{ {
throw new Exception($"Implementation fault, {itemsControlTemplateName} not found in template."); throw new Exception($"Implementation fault, {itemsControlTemplateName} not found in template.");
} }
} }
private static void OnDataSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) private static void OnDataSourcePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
@ -100,4 +131,47 @@ public class MultiFormatDataView : Control
PropertyGroupDescription groupDescription = new(nameof(DataViewModel.LineIdentifier)); PropertyGroupDescription groupDescription = new(nameof(DataViewModel.LineIdentifier));
view.GroupDescriptions.Add(groupDescription); 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:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:MultiTerm.Wpf.CustomControl" 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 TargetType="{x:Type local:MultiFormatDataView}">
<Style.Resources> <Style.Resources>
<SolidColorBrush x:Key="CHAR_Background" Color="#B4EBEB"/> <SolidColorBrush x:Key="CHAR_Background" Color="#B4EBEB"/>
<SolidColorBrush x:Key="HEX_Background" Color="#C8C8FF"/> <SolidColorBrush x:Key="HEX_Background" Color="#C8C8FF"/>
<SolidColorBrush x:Key="BIN_Background" Color="#C8FFC8"/> <SolidColorBrush x:Key="BIN_Background" Color="#C8FFC8"/>
<DataTemplate x:Key="dataContainerTemplate"> <DataTemplate x:Key="dataContainerTemplate" DataType="vm:DataViewModel">
<StackPanel Orientation="Vertical" Margin="0 0 5 0"> <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 --> <!-- Character -->
<Border BorderThickness="0"> <Border BorderThickness="0">
<Label Content="{Binding DisplayStringUtf16}"> <Label Content="{Binding DisplayStringUtf16}">
@ -83,11 +114,15 @@
<ControlTemplate TargetType="{x:Type local:MultiFormatDataView}"> <ControlTemplate TargetType="{x:Type local:MultiFormatDataView}">
<DockPanel> <DockPanel>
<GroupBox Header="Display Formats" DockPanel.Dock="Top"> <GroupBox Header="Display Formats" DockPanel.Dock="Top">
<StackPanel Orientation="Horizontal" > <DockPanel LastChildFill="False">
<CheckBox Content="Character" x:Name="cbCharacter" Padding="20 0" IsChecked="True"/> <CheckBox DockPanel.Dock="Left" Content="Character" VerticalAlignment="Center" x:Name="cbCharacter" Padding="20 0" IsChecked="True"/>
<CheckBox Content="Hexadecimal" x:Name="cbHex" Padding="20 0"/> <CheckBox DockPanel.Dock="Left" Content="Hexadecimal" VerticalAlignment="Center" x:Name="cbHex" Padding="20 0"/>
<CheckBox Content="Binary" x:Name="cbBin" Padding="20 0"/> <CheckBox DockPanel.Dock="Left" Content="Binary" VerticalAlignment="Center" x:Name="cbBin" Padding="20 0"/>
</StackPanel> <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> </GroupBox>
<ListView Name="itemsControl" <ListView Name="itemsControl"
ItemsSource="{TemplateBinding DataSource}" ItemsSource="{TemplateBinding DataSource}"
@ -96,6 +131,7 @@
ScrollViewer.PanningMode="VerticalOnly" ScrollViewer.PanningMode="VerticalOnly"
HorizontalAlignment="Left" HorizontalAlignment="Left"
VirtualizingPanel.IsVirtualizingWhenGrouping="True" VirtualizingPanel.IsVirtualizingWhenGrouping="True"
VirtualizingPanel.CacheLengthUnit="Item"
ItemTemplate="{StaticResource dataContainerTemplate}"> ItemTemplate="{StaticResource dataContainerTemplate}">
<ListView.ItemContainerStyle> <ListView.ItemContainerStyle>
@ -104,7 +140,7 @@
<Setter Property="VerticalContentAlignment" Value="Stretch" /> <Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style> </Style>
</ListView.ItemContainerStyle> </ListView.ItemContainerStyle>
<ListView.ItemsPanel> <ListView.ItemsPanel>
<ItemsPanelTemplate> <ItemsPanelTemplate>
<wpftk:VirtualizingWrapPanel <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