WPF 改进 WrapPanel 右侧填充
Posted dotNET跨平台
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了WPF 改进 WrapPanel 右侧填充相关的知识,希望对你有一定的参考价值。
WPF 改进 WrapPanel 右侧填充
本文经原作者授权以原创方式二次分享,欢迎转载、分享。
WPF 改进 WrapPanel 右边缘填充
作者:陈-林-赵-魏|驚鏵
原文链接[1]:https://www.cnblogs.com/wandia/p/17084881.html
目的:改进下
WrapPanel
, 多实现一个空间超出时候的充满效果,可以参考VS
的Team
中git
面板的那个,实现一个 类似git
提交代码 最后一个item
充满整行的效果。
1) WrapPanelFill.cs
代码如下:
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
namespace WrapPanelFillDemo
/// <summary>
/// 2023-02-02
/// WrapPanel改进后,增加了填充式布局,转载请保留博客地址!
/// 来源:https://www.cnblogs.com/wandia/p/17084881.html
/// 作者:陈-林-赵-魏
/// WrapPanel改进,增加了设置元素宽度高度时候填充式铺满
/// 代码改自 Microsoft WrapPanel 源码
/// </summary>
public class WrapPanelFill : WrapPanel
#region 依赖属性 是否填充式布局
public bool IsAdaptiveLayout
get return (bool)GetValue(IsAdaptiveLayoutProperty);
set SetValue(IsAdaptiveLayoutProperty, value);
public static readonly DependencyProperty IsAdaptiveLayoutProperty =
DependencyProperty.Register("IsAdaptiveLayout", typeof(bool), typeof(WrapPanelFill), new UIPropertyMetadata(false, OnIsAdaptiveLayout_ProperthChanged));
private static void OnIsAdaptiveLayout_ProperthChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
WrapPanelFill fill = d as WrapPanelFill;
if (fill != null) fill.InvalidateMeasure();
#endregion
#region 浮点数比较静态方法
private const double DBL_EPSILON = 2.2204460492503131e-016; /* smallest such that 1.0+DBL_EPSILON != 1.0 */
private static bool DoubleAreClose(double value1, double value2)
//in case they are Infinities (then epsilon check does not work)
if (value1 == value2)
return true;
// This computes (|value1-value2| / (|value1| + |value2| + 10.0)) < DBL_EPSILON
double eps = (Math.Abs(value1) + Math.Abs(value2) + 10.0) * DBL_EPSILON;
double delta = value1 - value2;
return -eps < delta && eps > delta;
private static bool DoubleGreaterThan(double value1, double value2)
return value1 > value2 && !DoubleAreClose(value1, value2);
#endregion
#region 是否设置元素宽度高度
private bool IsItemWidthSet get return !double.IsNaN(this.ItemWidth) && this.ItemWidth > 0;
private bool IsItemHeightSet get return !double.IsNaN(this.ItemHeight) && this.ItemHeight > 0;
#endregion
#region MeasureOverride
/// <summary>
/// <see cref="FrameworkElement.MeasureOverride" />
/// </summary>
protected override Size MeasureOverride(Size constraint)
UVSize uvConstraint = new UVSize(Orientation, constraint.Width, constraint.Height);
UVSize curLineSize = new UVSize(Orientation);
UVSize panelSize = new UVSize(Orientation);
Size childConstraint = GetConstraintSize(constraint);
UIElementCollection children = InternalChildren;
for (int i = 0, count = children.Count; i < count; i++)
UIElement child = children[i];
if (child == null) continue;
//Flow passes its own constrint to children
child.Measure(childConstraint);
//this is the size of the child in UV space
UVSize sz = new UVSize(
Orientation,
(IsItemWidthSet ? childConstraint.Width : child.DesiredSize.Width),
(IsItemHeightSet ? childConstraint.Height : child.DesiredSize.Height));
if (DoubleGreaterThan(curLineSize.U + sz.U, uvConstraint.U))
//need to switch to another line
panelSize.U = Math.Max(curLineSize.U, panelSize.U);
panelSize.V += curLineSize.V;
curLineSize = sz;
if (DoubleGreaterThan(sz.U, uvConstraint.U))
//the element is wider then the constrint - give it a separate line
panelSize.U = Math.Max(sz.U, panelSize.U);
panelSize.V += sz.V;
curLineSize = new UVSize(Orientation); //用于存放全新1行狂赌
else
//continue to accumulate a line
curLineSize.U += sz.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
//the last line size, if any should be added
panelSize.U = Math.Max(curLineSize.U, panelSize.U);
panelSize.V += curLineSize.V;
//go from UV space to W/H space
return new Size(panelSize.Width, panelSize.Height);
//得到元素测量时所用宽度
private Size GetConstraintSize(Size constraint)
int visibleCount = this.InternalChildren.Cast<UIElement>().Count(p => p != null && p.Visibility != Visibility.Collapsed);
Size childConstraint = new Size(constraint.Width, constraint.Height);
if (IsItemWidthSet == true)
if (Orientation == Orientation.Horizontal && !double.IsInfinity(constraint.Width) && this.IsAdaptiveLayout == true)
var count = Math.Floor(constraint.Width / this.ItemWidth); //元素个数
if (visibleCount >= count)
var averageWidth = constraint.Width / Math.Max(count, 1); //平均宽度
childConstraint.Width = averageWidth;
else if (visibleCount > 0)
childConstraint.Width = constraint.Width / visibleCount;
else
childConstraint.Width = this.ItemWidth;
if (IsItemHeightSet == true)
if (Orientation == Orientation.Vertical && !double.IsInfinity(constraint.Height) && this.IsAdaptiveLayout == true)
var count = Math.Floor(constraint.Height / this.ItemHeight); //元素个数
if (visibleCount >= count)
var averageHeight = constraint.Height / Math.Max(count, 1); //平均宽度
childConstraint.Height = averageHeight;
else if (visibleCount > 0)
childConstraint.Height = constraint.Height / visibleCount;
else
childConstraint.Height = this.ItemHeight;
return childConstraint;
#endregion
#region ArrangeOverride
/// <summary>
/// <see cref="FrameworkElement.ArrangeOverride" />
/// </summary>
protected override Size ArrangeOverride(Size finalSize)
int firstInLine = 0;
double accumulatedV = 0;
UVSize uvConstraint = new UVSize(Orientation, finalSize.Width, finalSize.Height);
UVSize curLineSize = new UVSize(Orientation);
Size childConstraint = GetConstraintSize(finalSize);
bool useItemU = (Orientation == Orientation.Horizontal ? IsItemWidthSet : IsItemHeightSet);
double itemU = (Orientation == Orientation.Horizontal ? childConstraint.Width : childConstraint.Height);
UIElementCollection children = InternalChildren;
for (int i = 0, count = children.Count; i < count; i++)
UIElement child = children[i];
if (child == null) continue;
UVSize sz = new UVSize(
Orientation,
(IsItemWidthSet ? childConstraint.Width : child.DesiredSize.Width),
(IsItemHeightSet ? childConstraint.Height : child.DesiredSize.Height));
if (DoubleGreaterThan(curLineSize.U + sz.U, uvConstraint.U))
//need to switch to another line
arrangeLine(accumulatedV, curLineSize.V, firstInLine, i, useItemU, itemU);
accumulatedV += curLineSize.V;
curLineSize = sz;
if (DoubleGreaterThan(sz.U, uvConstraint.U)) //the element is wider then the constraint - give it a separate line
//switch to next line which only contain one element
arrangeLine(accumulatedV, sz.V, i, ++i, useItemU, itemU);
accumulatedV += sz.V;
curLineSize = new UVSize(Orientation);
firstInLine = i;
else
//continue to accumulate a line
curLineSize.U += sz.U;
curLineSize.V = Math.Max(sz.V, curLineSize.V);
//arrange the last line, if any
if (firstInLine < children.Count)
arrangeLine(accumulatedV, curLineSize.V, firstInLine, children.Count, useItemU, itemU);
return finalSize;
private void arrangeLine(double v, double lineV, int start, int end, bool useItemU, double itemU)
double u = 0;
bool isHorizontal = (Orientation == Orientation.Horizontal);
UIElementCollection children = InternalChildren;
for (int i = start; i < end; i++)
UIElement child = children[i];
if (child != null)
UVSize childSize = new UVSize(Orientation, child.DesiredSize.Width, child.DesiredSize.Height);
double layoutSlotU = (useItemU ? itemU : childSize.U);
child.Arrange(new Rect(
(isHorizontal ? u : v),
(isHorizontal ? v : u),
(isHorizontal ? layoutSlotU : lineV),
(isHorizontal ? lineV : layoutSlotU)));
u += layoutSlotU;
#endregion
#region Private Struct
private struct UVSize
internal UVSize(Orientation orientation, double width, double height)
U = V = 0d;
_orientation = orientation;
Width = width;
Height = height;
internal UVSize(Orientation orientation)
U = V = 0d;
_orientation = orientation;
internal double U;
internal double V;
private Orientation _orientation;
internal double Width
get return (_orientation == Orientation.Horizontal ? U : V);
set if (_orientation == Orientation.Horizontal) U = value; else V = value;
internal double Height
get return (_orientation == Orientation.Horizontal ? V : U);
set if (_orientation == Orientation.Horizontal) V = value; else U = value;
#endregion
2) MainWindow.xaml
代码如下:
<ws:Window x:Class="WrapPanelFillDemo.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ws="https://github.com/WPFDevelopersOrg/WPFDevelopers"
xmlns:local="clr-namespace:WrapPanelFillDemo"
mc:Ignorable="d"
Title="Team Explorer-Home" Height="414" Width="324">
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Margin" Value="2 0"/>
</Style>
</Window.Resources>
<TabControl>
<TabItem Header="情景1(高度充满)">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock FontWeight="Bold" Text="元素宽度高度设置时 填充式 WrapPanel(陈-林-赵-魏)" Margin="0,5"/>
<WrapPanel Grid.Row="1" Margin="0,2">
<CheckBox x:Name="ChkAdaptiveLayout" IsChecked="True" Content="填充式布局"
VerticalAlignment="Center" VerticalContentAlignment="Center"
Margin="0,0,50,0"/>
<CheckBox x:Name="ChkVertical" IsChecked="False" Content="垂直布局"
VerticalAlignment="Center" VerticalContentAlignment="Center"
Margin="0,0,50,0"/>
<TextBlock Text="元素宽度" VerticalAlignment="Center"/>
<TextBox x:Name="txtItemWidth" MinWidth="120" VerticalContentAlignment="Center"
Text="Binding ElementName=WrapPanelFill,Path=ItemWidth,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged"/>
<TextBlock Text="元素高度" VerticalAlignment="Center"/>
<TextBox x:Name="txtItemHeight" MinWidth="120" VerticalContentAlignment="Center"
Text="Binding ElementName=WrapPanelFill,Path=ItemHeight,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged"/>
<TextBlock Text="输入NaN代表宽度不确定"/>
</WrapPanel>
<local:WrapPanelFill x:Name="WrapPanelFill" IsAdaptiveLayout="Binding ElementName=ChkAdaptiveLayout,Path=IsChecked,Mode=TwoWay" ItemWidth="150" Grid.Row="3"
Orientation="Horizontal" >
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#F05033" Width="4"/>
<Grid Margin="5">
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FFB8B2B2" />
</Grid>
<TextBlock Text="Changed" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#F05033" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FFDCA1A1" />
</Grid>
<TextBlock Text="Branches" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#FF3333F0" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FFB5B9BD" />
</Grid>
<TextBlock Text="Sync" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#FF616161" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FF3E3E3E" />
</Grid>
<TextBlock Text="Setting" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FF555E85" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#FF616161" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FF93B6AA" />
</Grid>
<TextBlock Text="Others" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
</local:WrapPanelFill>
<Border Grid.Row="3" BorderThickness="1" BorderBrush="Red" Margin="0,4" Visibility="Collapsed">
<Label Content="这里是VS扩展git源码提交部分界面不实现!"/>
</Border>
</Grid>
</TabItem>
<TabItem Header="情景2(高度Auto)">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock FontWeight="Bold" Text="元素宽度高度设置时 填充式 WrapPanel(陈-林-赵-魏)" Margin="0,5"/>
<WrapPanel Grid.Row="1" Margin="0,2">
<CheckBox x:Name="ChkAdaptiveLayout2" IsChecked="True" Content="填充式布局"
VerticalAlignment="Center" VerticalContentAlignment="Center"
Margin="0,0,50,0"/>
<CheckBox x:Name="ChkVertical2" IsChecked="False" Content="垂直布局"
VerticalAlignment="Center" VerticalContentAlignment="Center"
Margin="0,0,50,0"/>
<TextBlock Text="元素宽度" VerticalAlignment="Center"/>
<TextBox x:Name="txtItemWidth2" MinWidth="120" VerticalContentAlignment="Center"
Text="Binding ElementName=WrapPanelFill2,Path=ItemWidth,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged"/>
<TextBlock Text="元素高度" VerticalAlignment="Center"/>
<TextBox x:Name="txtItemHeight2" MinWidth="120" VerticalContentAlignment="Center"
Text="Binding ElementName=WrapPanelFill2,Path=ItemHeight,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged"/>
</WrapPanel>
<local:WrapPanelFill x:Name="WrapPanelFill2" IsAdaptiveLayout="Binding ElementName=ChkAdaptiveLayout2,Path=IsChecked,Mode=TwoWay" ItemWidth="150" Grid.Row="2"
Orientation="Horizontal" ItemHeight="40">
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#F05033" Width="4"/>
<Grid Margin="5">
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FFB8B2B2" />
</Grid>
<TextBlock Text="Changed" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#F05033" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FFDCA1A1" />
</Grid>
<TextBlock Text="Branches" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#FF3333F0" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FFB5B9BD" />
</Grid>
<TextBlock Text="Sync" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#FF616161" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FF3E3E3E" />
</Grid>
<TextBlock Text="Setting" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FF555E85" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#FF616161" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FF93B6AA" />
</Grid>
<TextBlock Text="Others" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
</local:WrapPanelFill>
<Border Grid.Row="3" BorderThickness="1" BorderBrush="Red" Margin="0,4" Visibility="Visible">
<Label Content="这里是VS扩展git源码提交部分界面不实现!"/>
</Border>
</Grid>
</TabItem>
<TabItem Header="情景3(ScrollView中表现)">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock FontWeight="Bold" Text="元素宽度高度设置时 填充式 WrapPanel(陈-林-赵-魏)" Margin="0,5"/>
<WrapPanel Grid.Row="1" Margin="0,2">
<CheckBox x:Name="ChkAdaptiveLayout3" IsChecked="True" Content="填充式布局"
VerticalAlignment="Center" VerticalContentAlignment="Center"
Margin="0,0,50,0"/>
<CheckBox x:Name="ChkVertical3" IsChecked="False" Content="垂直布局"
VerticalAlignment="Center" VerticalContentAlignment="Center"
Margin="0,0,50,0"/>
<TextBlock Text="元素宽度" VerticalAlignment="Center"/>
<TextBox x:Name="txtItemWidth3" MinWidth="120" VerticalContentAlignment="Center"
Text="Binding ElementName=WrapPanelFill3,Path=ItemWidth,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged"/>
<TextBlock Text="元素高度" VerticalAlignment="Center"/>
<TextBox x:Name="txtItemHeight3" MinWidth="120" VerticalContentAlignment="Center"
Text="Binding ElementName=WrapPanelFill3,Path=ItemHeight,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged"/>
<TextBlock Text="输入NaN代表宽度不确定"/>
</WrapPanel>
<Border Grid.Row="3" Margin="40" BorderBrush="Red" BorderThickness="1">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<local:WrapPanelFill x:Name="WrapPanelFill3" IsAdaptiveLayout="Binding ElementName=ChkAdaptiveLayout3,Path=IsChecked,Mode=TwoWay" ItemWidth="150" Grid.Row="3"
Orientation="Horizontal" >
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#F05033" Width="4"/>
<Grid Margin="5">
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FFB8B2B2" />
</Grid>
<TextBlock Text="Changed" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#F05033" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FFDCA1A1" />
</Grid>
<TextBlock Text="Branches" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#FF3333F0" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FFB5B9BD" />
</Grid>
<TextBlock Text="Sync" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FFCFCFCF" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#FF616161" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FF3E3E3E" />
</Grid>
<TextBlock Text="Setting" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
<DockPanel MinHeight="35" Margin="0,0,5,2">
<DockPanel.Background>
<LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5">
<GradientStop Color="#FFA6A6A6" Offset="0"/>
<GradientStop Color="#FF555E85" Offset="1"/>
</LinearGradientBrush>
</DockPanel.Background>
<Rectangle Fill="#FF616161" Width="4"/>
<Grid Margin="5" >
<Ellipse StrokeThickness="2" Width="25" Height="25" Stroke="Black"/>
<Ellipse StrokeThickness="2" Width="17" Height="17" Fill="#FF93B6AA" />
</Grid>
<TextBlock Text="Others" FontWeight="Medium" FontSize="16" VerticalAlignment="Center"/>
</DockPanel>
</local:WrapPanelFill>
</ScrollViewer>
</Border>
</Grid>
</TabItem>
</TabControl>
</ws:Window>
参考资料
[1]
原文链接: https://www.cnblogs.com/wandia/p/17084881.html
以上是关于WPF 改进 WrapPanel 右侧填充的主要内容,如果未能解决你的问题,请参考以下文章
WPF: WrapPanel 容器的数据绑定(动态生成控件遍历)
WPF:带有 WrapPanel 的 ListBox,垂直滚动问题