优化更新代码,添加界面功能并整合
This commit is contained in:
31
WPFluent/Controls/GridView/GridView.cs
Normal file
31
WPFluent/Controls/GridView/GridView.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
|
||||
|
||||
|
||||
namespace WPFluent.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Extends <see cref="System.Windows.Controls.GridView"/> to use WPFluent custom styles
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// To use this enhanced GridView in a ListView: <code lang="xml"> /// <ListView> /// <ListView.View>
|
||||
/// /// <local:GridView> /// <GridViewColumn Header="First Name"
|
||||
/// DisplayMemberBinding="{Binding FirstName}"/> /// <GridViewColumn Header="Last Name"
|
||||
/// DisplayMemberBinding="{Binding LastName}"/> /// </local:GridView> /// </ListView.View>
|
||||
/// /// </ListView> ///</code>
|
||||
/// </example>
|
||||
public class GridView : System.Windows.Controls.GridView
|
||||
{
|
||||
static GridView()
|
||||
{
|
||||
ResourceDictionary resourceDict = new()
|
||||
{
|
||||
Source = new Uri("pack://application:,,,/WPFluent;component/Controls/GridView/GridViewColumnHeader.xaml"),
|
||||
};
|
||||
|
||||
Style defaultStyle = (Style)resourceDict["UiGridViewColumnHeaderStyle"];
|
||||
|
||||
ColumnHeaderContainerStyleProperty.OverrideMetadata(
|
||||
typeof(GridView),
|
||||
new FrameworkPropertyMetadata(defaultStyle));
|
||||
}
|
||||
}
|
||||
119
WPFluent/Controls/GridView/GridViewColumn.cs
Normal file
119
WPFluent/Controls/GridView/GridViewColumn.cs
Normal file
@@ -0,0 +1,119 @@
|
||||
|
||||
|
||||
|
||||
using System.Reflection;
|
||||
|
||||
namespace WPFluent.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Extends <see cref="System.Windows.Controls.GridViewColumn"/> with MinWidth and MaxWidth properties. It can be used
|
||||
/// with <see cref="ListView"/> when in GridView mode.
|
||||
/// </summary>
|
||||
/// <example>
|
||||
/// <code lang="xml"> /// <ui:ListView> /// <ui:ListView.View> /// <ui:GridView> ///
|
||||
/// <ui:GridViewColumn /// MinWidth="100" /// MaxWidth="200" ///
|
||||
/// DisplayMemberBinding="{Binding FirstName}" /// Header="First Name" /> ///
|
||||
/// </ui:GridView> /// </ui:ListView.View> /// </ui:ListView> ///</code>
|
||||
/// </example>
|
||||
public class GridViewColumn : System.Windows.Controls.GridViewColumn
|
||||
{
|
||||
// use reflection to get the `_desiredWidth` private field.
|
||||
private static readonly Lazy<FieldInfo> _desiredWidthField = new(
|
||||
() => typeof(System.Windows.Controls.GridViewColumn).GetField(
|
||||
"_desiredWidth",
|
||||
BindingFlags.NonPublic | BindingFlags.Instance) ??
|
||||
throw new InvalidOperationException("The `_desiredWidth` field was not found."));
|
||||
|
||||
// use reflection to get the `UpdateActualWidth` private method.
|
||||
private static readonly Lazy<MethodInfo> _updateActualWidthMethod = new(
|
||||
() =>
|
||||
{
|
||||
MethodInfo methodInfo =
|
||||
typeof(System.Windows.Controls.GridViewColumn).GetMethod(
|
||||
"UpdateActualWidth",
|
||||
BindingFlags.NonPublic | BindingFlags.Instance) ??
|
||||
throw new InvalidOperationException("The `UpdateActualWidth` method was not found.");
|
||||
return methodInfo;
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="MaxWidth"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty MaxWidthProperty = DependencyProperty.Register(
|
||||
nameof(MaxWidth),
|
||||
typeof(double),
|
||||
typeof(GridViewColumn),
|
||||
new FrameworkPropertyMetadata(double.PositiveInfinity, OnMaxWidthChanged));
|
||||
|
||||
/// <summary>
|
||||
/// Identifies the <see cref="MinWidth"/> dependency property.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty MinWidthProperty = DependencyProperty.Register(
|
||||
nameof(MinWidth),
|
||||
typeof(double),
|
||||
typeof(GridViewColumn),
|
||||
new FrameworkPropertyMetadata(0.0, OnMinWidthChanged));
|
||||
|
||||
private static void OnMaxWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if(d is not GridViewColumn self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.OnMaxWidthChanged(e);
|
||||
}
|
||||
|
||||
private static void OnMinWidthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if(d is not GridViewColumn self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self.OnMinWidthChanged(e);
|
||||
}
|
||||
|
||||
private static FieldInfo DesiredWidthField => _desiredWidthField.Value;
|
||||
|
||||
private static MethodInfo UpdateActualWidthMethod => _updateActualWidthMethod.Value;
|
||||
|
||||
protected virtual void OnMaxWidthChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
// Hook for derived classes to react to MaxWidth property changes
|
||||
}
|
||||
|
||||
protected virtual void OnMinWidthChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
// Hook for derived classes to react to MinWidth property changes
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the desired width of the column to be clamped between MinWidth and MaxWidth).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Uses reflection to directly set the private `_desiredWidth` field on the
|
||||
/// `System.Windows.Controls.GridViewColumn`.
|
||||
/// </remarks>
|
||||
/// <exception cref="InvalidOperationException">
|
||||
/// Thrown if reflection fails to access the `_desiredWidth` field
|
||||
/// </exception>
|
||||
internal void UpdateDesiredWidth()
|
||||
{
|
||||
double currentWidth = (double)(DesiredWidthField.GetValue(this) ??
|
||||
throw new InvalidOperationException("Failed to get the current `_desiredWidth`."));
|
||||
double clampedWidth = Math.Max(MinWidth, Math.Min(currentWidth, MaxWidth));
|
||||
DesiredWidthField.SetValue(this, clampedWidth);
|
||||
_ = UpdateActualWidthMethod.Invoke(this, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// gets or sets the maximum width of the column.
|
||||
/// </summary>
|
||||
public double MaxWidth { get => (double)GetValue(MaxWidthProperty); set => SetValue(MaxWidthProperty, value); }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the minimum width of the column.
|
||||
/// </summary>
|
||||
public double MinWidth { get => (double)GetValue(MinWidthProperty); set => SetValue(MinWidthProperty, value); }
|
||||
}
|
||||
120
WPFluent/Controls/GridView/GridViewColumnHeader.xaml
Normal file
120
WPFluent/Controls/GridView/GridViewColumnHeader.xaml
Normal file
@@ -0,0 +1,120 @@
|
||||
<!--
|
||||
This Source Code Form is subject to the terms of the MIT License.
|
||||
If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
|
||||
Copyright (C) Leszek Pomianowski and WPF UI Contributors.
|
||||
All Rights Reserved.
|
||||
-->
|
||||
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:WPFluent.Controls">
|
||||
|
||||
<Style x:Key="UiGridViewColumnHeaderStyle" TargetType="GridViewColumnHeader">
|
||||
<Style.Triggers>
|
||||
<Trigger Property="GridViewColumnHeader.Role" Value="Floating">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="GridViewColumnHeader">
|
||||
<Canvas Name="PART_FloatingHeaderCanvas">
|
||||
<Rectangle
|
||||
Width="{TemplateBinding ActualWidth}"
|
||||
Height="{TemplateBinding ActualHeight}"
|
||||
Fill="#FF000000"
|
||||
Opacity="0.5" />
|
||||
</Canvas>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
<Trigger Property="GridViewColumnHeader.Role" Value="Padding">
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="GridViewColumnHeader">
|
||||
<Border
|
||||
Name="HeaderBorder"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding Border.BorderBrush}"
|
||||
BorderThickness="0,0,0,0" />
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Trigger>
|
||||
</Style.Triggers>
|
||||
<Setter Property="HorizontalContentAlignment" Value="Left" />
|
||||
<Setter Property="VerticalContentAlignment" Value="Center" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="BorderBrush" Value="Transparent" />
|
||||
<Setter Property="BorderThickness" Value="0,0,0,0" />
|
||||
<Setter Property="Margin" Value="0,0,0,0" />
|
||||
<Setter Property="Padding" Value="0,2" />
|
||||
<Setter Property="Foreground" Value="{DynamicResource TextFillColorPrimaryBrush}" />
|
||||
<Setter Property="FontWeight" Value="Bold" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="GridViewColumnHeader">
|
||||
<Grid>
|
||||
<Border
|
||||
Name="HeaderBorder"
|
||||
Background="{TemplateBinding Background}"
|
||||
BorderBrush="{TemplateBinding BorderBrush}"
|
||||
BorderThickness="0,0,0,0"
|
||||
CornerRadius="{DynamicResource ControlCornerRadius}">
|
||||
<Border Margin="6,0,0,0" Padding="{TemplateBinding Padding}">
|
||||
<ContentPresenter
|
||||
Name="HeaderContent"
|
||||
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding Content}"
|
||||
ContentStringFormat="{TemplateBinding ContentStringFormat}"
|
||||
ContentTemplate="{TemplateBinding ContentTemplate}"
|
||||
RecognizesAccessKey="True"
|
||||
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
|
||||
<!--<TextBlock Text="{TemplateBinding Content}" />-->
|
||||
</Border>
|
||||
</Border>
|
||||
<Canvas>
|
||||
<Thumb Name="PART_HeaderGripper">
|
||||
<Thumb.Style>
|
||||
<Style TargetType="Thumb">
|
||||
<Setter Property="Canvas.Right" Value="-9" />
|
||||
<Setter Property="Width" Value="18" />
|
||||
<Setter Property="Height" Value="{Binding Path=ActualHeight, RelativeSource={RelativeSource Mode=TemplatedParent}}" />
|
||||
<Setter Property="Padding" Value="0,0,0,0" />
|
||||
<Setter Property="Background" Value="Transparent" />
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="Thumb">
|
||||
<Border Padding="{TemplateBinding Padding}" Background="#00FFFFFF">
|
||||
<Rectangle
|
||||
Width="1"
|
||||
HorizontalAlignment="Center"
|
||||
Fill="{TemplateBinding Background}" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
</Thumb.Style>
|
||||
</Thumb>
|
||||
</Canvas>
|
||||
</Grid>
|
||||
<ControlTemplate.Triggers>
|
||||
<Trigger Property="IsMouseOver" Value="True">
|
||||
<Setter TargetName="HeaderBorder" Property="Background" Value="{DynamicResource ListViewItemBackgroundPointerOver}" />
|
||||
<Setter TargetName="PART_HeaderGripper" Property="Background" Value="Transparent" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsPressed" Value="True">
|
||||
<Setter TargetName="HeaderBorder" Property="Background" Value="Transparent" />
|
||||
<Setter TargetName="PART_HeaderGripper" Property="Visibility" Value="Hidden" />
|
||||
</Trigger>
|
||||
<Trigger Property="IsEnabled" Value="False">
|
||||
<Setter Property="TextElement.Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}" />
|
||||
</Trigger>
|
||||
</ControlTemplate.Triggers>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
||||
</Style>
|
||||
|
||||
</ResourceDictionary>
|
||||
26
WPFluent/Controls/GridView/GridViewHeaderRowIndicator.xaml
Normal file
26
WPFluent/Controls/GridView/GridViewHeaderRowIndicator.xaml
Normal file
@@ -0,0 +1,26 @@
|
||||
<!--
|
||||
This Source Code Form is subject to the terms of the MIT License.
|
||||
If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
|
||||
Copyright (C) Leszek Pomianowski and WPF UI Contributors.
|
||||
All Rights Reserved.
|
||||
-->
|
||||
|
||||
<ResourceDictionary
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:controls="clr-namespace:WPFluent.Controls">
|
||||
|
||||
<ControlTemplate x:Key="GridViewHeaderRowIndicatorTemplate" TargetType="Separator">
|
||||
<Border>
|
||||
<Rectangle
|
||||
Width="3"
|
||||
Height="18"
|
||||
Margin="0"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Fill="{DynamicResource ListViewItemPillFillBrush}"
|
||||
RadiusX="2"
|
||||
RadiusY="2" />
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
</ResourceDictionary>
|
||||
83
WPFluent/Controls/GridView/GridViewHeaderRowPresenter.cs
Normal file
83
WPFluent/Controls/GridView/GridViewHeaderRowPresenter.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
|
||||
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace WPFluent.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Extends <see cref="System.Windows.Controls.GridViewHeaderRowPresenter"/>, and adds layout support for <see
|
||||
/// cref="GridViewColumn"/>, which can have <see cref="GridViewColumn.MinWidth"/> and <see
|
||||
/// cref="GridViewColumn.MaxWidth"/>.
|
||||
/// </summary>
|
||||
public class GridViewHeaderRowPresenter : System.Windows.Controls.GridViewHeaderRowPresenter
|
||||
{
|
||||
public GridViewHeaderRowPresenter() { Loaded += OnLoaded; }
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e) { UpdateIndicatorStyle(); }
|
||||
|
||||
private void UpdateIndicatorStyle()
|
||||
{
|
||||
FieldInfo? indicatorField = typeof(System.Windows.Controls.GridViewHeaderRowPresenter).GetField(
|
||||
"_indicator",
|
||||
BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
|
||||
if (indicatorField == null)
|
||||
{
|
||||
Debug.WriteLine("Failed to get the _indicator field");
|
||||
return;
|
||||
}
|
||||
|
||||
if (indicatorField.GetValue(this) is Separator indicator)
|
||||
{
|
||||
indicator.Margin = new Thickness(0);
|
||||
indicator.Width = 3.0;
|
||||
|
||||
ResourceDictionary resourceDictionary = new()
|
||||
{
|
||||
Source =
|
||||
new Uri(
|
||||
"pack://application:,,,/WPFluent;component/Controls/GridView/GridViewHeaderRowIndicator.xaml",
|
||||
UriKind.Absolute),
|
||||
};
|
||||
|
||||
if (resourceDictionary["GridViewHeaderRowIndicatorTemplate"] is ControlTemplate template)
|
||||
{
|
||||
indicator.Template = template;
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.WriteLine("Failed to get the GridViewHeaderRowIndicatorTemplate");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size arrangeSize)
|
||||
{
|
||||
// update the desired width of each column (clamps desiredwidth to MinWidth and MaxWidth)
|
||||
if (Columns != null)
|
||||
{
|
||||
foreach (GridViewColumn column in Columns.OfType<GridViewColumn>())
|
||||
{
|
||||
column.UpdateDesiredWidth();
|
||||
}
|
||||
}
|
||||
|
||||
return base.ArrangeOverride(arrangeSize);
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size constraint)
|
||||
{
|
||||
if (Columns != null)
|
||||
{
|
||||
foreach (GridViewColumn column in Columns.OfType<GridViewColumn>())
|
||||
{
|
||||
column.UpdateDesiredWidth();
|
||||
}
|
||||
}
|
||||
|
||||
return base.MeasureOverride(constraint);
|
||||
}
|
||||
}
|
||||
40
WPFluent/Controls/GridView/GridViewRowPresenter.cs
Normal file
40
WPFluent/Controls/GridView/GridViewRowPresenter.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
|
||||
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace WPFluent.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Extends <see cref="System.Windows.Controls.GridViewRowPresenter"/>, and adds header row layout support for <see
|
||||
/// cref="GridViewColumn"/>, which can have <see cref="GridViewColumn.MinWidth"/> and <see
|
||||
/// cref="GridViewColumn.MaxWidth"/>.
|
||||
/// </summary>
|
||||
public class GridViewRowPresenter : System.Windows.Controls.GridViewRowPresenter
|
||||
{
|
||||
protected override Size ArrangeOverride(Size arrangeSize)
|
||||
{
|
||||
// update the desired width of each column (clamps desiredwidth to MinWidth and MaxWidth)
|
||||
if(Columns != null)
|
||||
{
|
||||
foreach(GridViewColumn column in Columns.OfType<GridViewColumn>())
|
||||
{
|
||||
column.UpdateDesiredWidth();
|
||||
}
|
||||
}
|
||||
|
||||
return base.ArrangeOverride(arrangeSize);
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size constraint)
|
||||
{
|
||||
if(Columns != null)
|
||||
{
|
||||
foreach(GridViewColumn column in Columns.OfType<GridViewColumn>())
|
||||
{
|
||||
column.UpdateDesiredWidth();
|
||||
}
|
||||
}
|
||||
|
||||
return base.MeasureOverride(constraint);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user