WPF 改进 WrapPanel 右侧填充

article/2025/10/25 7:02:17

 WPF 改进 WrapPanel 右侧填充

本文经原作者授权以原创方式二次分享,欢迎转载、分享。

WPF 改进 WrapPanel 右边缘填充

作者:陈-林-赵-魏|驚鏵

原文链接[1]:https://www.cnblogs.com/wandia/p/17084881.html

  • 目的:改进下WrapPanel, 多实现一个空间超出时候的充满效果,可以参考VSTeamgit面板的那个,实现一个 类似git提交代码 最后一个item充满整行的效果。

f5e11a532b882bdb4bbc86e75080f9a1.png 32a1768f74e2391966f59d5c5d57c1ad.png

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_EPSILONdouble 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 childrenchild.Measure(childConstraint);//this is the size of the child in UV spaceUVSize 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 linepanelSize.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 linecurLineSize.U += sz.U;curLineSize.V = Math.Max(sz.V, curLineSize.V);}}//the last line size, if any should be addedpanelSize.U = Math.Max(curLineSize.U, panelSize.U);panelSize.V += curLineSize.V;//go from UV space to W/H spacereturn 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 linearrangeLine(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 elementarrangeLine(accumulatedV, sz.V, i, ++i, useItemU, itemU);accumulatedV += sz.V;curLineSize = new UVSize(Orientation);}firstInLine = i;}else{   //continue to accumulate a linecurLineSize.U += sz.U;curLineSize.V = Math.Max(sz.V, curLineSize.V);}}//arrange the last line, if anyif (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 Structprivate 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>
37de44a52c9c02639e852708bb270bf8.gif

参考资料

[1]

原文链接: https://www.cnblogs.com/wandia/p/17084881.html


http://chatgpt.dhexx.cn/article/q5MEwBks.shtml

相关文章

WrapPanel 实现虚拟化

WrapPanel 实现虚拟化 控件名&#xff1a;VirtualizingWrapPanel 作者&#xff1a;WPFDevelopersOrg 原文链接&#xff1a; https://github.com/WPFDevelopersOrg/WPFDevelopers 框架使用大于等于.NET40&#xff1b;Visual Studio 2022;项目使用 MIT 开源许可协议&#xff1…

对wpf 的入门记录总结----面板控件Canvas、WrapPanel、StackPanel、DockPanel

面板是WPF裡其中一個很重要的控件。 面板扮演著裝載其他控件的容器的角色&#xff0c;同時也控制著頁面和視窗的佈局。 由於一個視窗只允許一個子控件&#xff0c;因此面板經常會被使用於分隔空間&#xff0c;這樣每個空間就會有一個控件或者面板。 wpf支持6种面板&#xff1…

listbox 表头自动换行_WPF让ListView或ListBox中的WrapPanel 自动换行

原文:WPF让ListView或ListBox中的WrapPanel 自动换行 在ListView或者ListBox中使用WrapPanel想让ItemTemplate中的内容像下图这样先横向平铺然后再纵向换行&#xff0c;默认设置是不能实现的。 图1. 横向平铺再纵向换行的效果示例 请注意最关键的在上面代码中第一行的“ScrollV…

WPF教程三:布局之WrapPanel面板(转 )

WPF教程三&#xff1a;布局之WrapPanel面板 WrapPanel&#xff1a;环绕面板 WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列&#xff0c;当长度或高度不够时就会自动调整进行换行&#xff0c;后续排序按照从上至下或从右至左的顺序进行。 Orientation——根据内容自…

WPF面板布局介绍Grid、StackPanel、DockPanel、WrapPanel

WPF面板布局介绍Grid、StackPanel、DockPanel、WrapPanel 回顾 上一篇&#xff0c;我们介绍了基本控件及控件的重要属性和用法&#xff0c;我们本篇详细介绍WPF中的几种布局容器及每种布局容器的使用场景&#xff0c;当 然这些都是本人在实际项目中的使用经验&#xff0c;可能…

2021-08-16 WPF控件专题 WrapPanel 控件详解

1.WrapPanel 控件介绍 流面板 子元素按顺序排列&#xff0c;如果按水平方向:从左到右&#xff0c;超出部分&#xff0c;自动换行到下一行 垂直 从上到下&#xff0c; 下一列 排列方向&#xff1a;Orientation ItemWidth ItemHeight 调整面板的尺寸时&#xff0c;内部子元素的…

.NET WPF(3)布局之WrapPanel面板

一.WPF&#xff08;3&#xff09;布局之WrapPane面板 1. WrapPanel&#xff1a;环绕面板 WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列&#xff0c;当长度或高度不够时就会自动调整进行换行&#xff0c;后续排序按照从上至下或从右至左的顺序进行。 Orie…

WPF编程基础入门 ——— 第三章 布局(五)布局面板WrapPanel

WPF布局——布局面板WrapPanel WPF——WrapPanel布局控件WrapPanel实例——十个按钮 WPF——WrapPanel布局控件 WrapPanel(自动折行面板)&#xff0c;允许任意多的子元素按照声明的先后顺序&#xff0c;从左往右摆放&#xff0c;摆满一行后&#xff0c;自动折行。折行面板的经…

WPF布局控件之WrapPanel

WrapPanel WrapPanel&#xff0c;英文意思是折叠容器&#xff0c;那到底是怎么个折叠法呢&#xff1f;如下&#xff1a; <Window x:Class"LearnLayout.WrapPanelWin"xmlns"http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x"ht…

.NET WPF教程(7)——布局介绍WrapPanel与StackPanel(②)

三. WrapPanel WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列&#xff0c;当长度或高度不够是就会自动调整进行换行&#xff0c;后续排序按照从上至下或从右至左的顺序进行。 Orientation——根据内容自动换行。当 Horizontal选项看上去类似于Windows资源管理器…

WPF 用代码实现WrapPanel右侧自动对齐(解决多余空白问题)

未处理前效果&#xff1a; 处理后效果&#xff1a; <Border Background"{StaticResource BorderBg}" BorderThickness"2" BorderBrush"{StaticResource BorderBrush}" CornerRadius"5" Padding"5" x:Name"SvK…

C# Grid StackPanel DockPanel WrapPanel

WPF面板布局介绍Grid、StackPanel、DockPanel、WrapPanel 回顾 上一篇&#xff0c;我们介绍了基本控件及控件的重要属性和用法&#xff0c;我们本篇详细介绍WPF中的几种布局容器及每种布局容器的使用场景&#xff0c;当 然这些都是本人在实际项目中的使用经验&#xff0c;可能…

WPF基础五:UI①布局元素WrapPanel

目录 WrapPanel WrapPanel类 XAML范例&#xff1a; C#代码 WrapPanel 按从左到右的顺序位置定位子元素&#xff0c;在包含框的边缘处将内容切换到下一行。 后续排序按照从上至下或从右至左的顺序进行&#xff0c;具体取决于 Orientation 属性的值。 WrapPanel包含UIElemen…

一个优化奇怪的 WrapPanel

一个优化奇怪的 WrapPanel 本文经原作者授权以原创方式二次分享&#xff0c;欢迎转载、分享。 一个优化奇怪的 WrapPanel 作者&#xff1a;陈-林-赵-魏 原文链接[1]&#xff1a;https://www.cnblogs.com/wandia/p/17092221.html FixToRB 附加属性&#xff0c;固定到【右边(水平…

WPF布局之WrapPanel与StackPanel

转载&#xff1a;https://www.cnblogs.com/Im-Victor/p/10565030.html 三. WrapPanel WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列&#xff0c;当长度或高度不够是就会自动调整进行换行&#xff0c;后续排序按照从上至下或从右至左的顺序进行。 Orientation——…

WrapPanel在不同页面渲染使用

WrapPanel渲染的使用 WrapPanel在UserControl用户控件的使用 页面控件的是渲染出来&#xff0c;在UserControl用户控件的使用无法直接使用&#xff0c;使用会出现空&#xff0c;没法渲染获取到WrapPanel控件。 没法渲染获取效果图&#xff1a; 想成功获取渲染获取到WrapPane…

WPF 入门教程WrapPanel介绍

WrapPanel将定位每个子控件的旁边&#xff0c;另外&#xff0c;水平方向&#xff08;默认值&#xff09;或垂直&#xff0c;直到没有更多的空间&#xff0c;在那里将换到下一行&#xff0c;然后继续。当您想要一个垂直或水平列表控件在没有更多空间时自动换行时使用它。 当 Wr…

WPF WrapPanel、UniformGrid、DockPanel介绍

WPF WrapPanel、UniformGrid、DockPanel介绍 WrapPanel WrapPanel , 具有在有限的容器范围内, 可以自动换行, 或者换列处理。具体则取决于WrapPanel的排列方式 (Orientation)。 Orientation"Horizontal"时各控件从左至右罗列&#xff0c;当面板长度不够时&#xff…

WPF控件之WrapPanel的用法

简单来说&#xff0c;WrapPanel就是一个可以行填充&#xff0c;自动换行。或者列填充&#xff0c;自动换列的一个布局容器。 如下所示&#xff0c;它会自动将10个button分成2行 <WrapPanel><Button Content"button1" /><Button Content"button…

WrapPanel:自动折行面板(环绕面板)基础简述

WrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列&#xff0c;当长度或高度不够时就会自动调整进行换行或换列&#xff0c;后续排序按照从上至下或从右至左的顺序进行。 Orientation——根据内容自动换行。当Orientation属性的值设置为 Horizontal&#xff1a;元素是…