基于WPF实现瀑布流控件

 更新时间:2024年02月22日 15:10:00   作者:WPF开发者  
这篇文章主要介绍了如何基于WPF实现简单的瀑布流控件,文中的示例代码讲解详细,对我们的学习或工作有一定帮助,需要的小伙伴可以参考一下

WPF 实现瀑布流控件

框架支持.NET4 至 .NET8;

Visual Studio 2022;

需求详见 ISSUE

实现代码

1)新增 WaterfallPanel.cs 代码如下:

  • WaterfallPanel 的自定义控件,继承自 VirtualizingPanel
  • WaterfallPanel 控件实现了瀑布流布局,即将多个子元素按照一定规则排列在面板中。该控件具有 Columns 和 Spacing 两个依赖属性,分别表示列数和每个子控件之间的间距。
  • MeasureOverride用于测量和排列子控件。在 WaterfallPanel 的 MeasureOverride 方法中,先清除了列高的记录,然后计算出每一列的高度并保存在一个 List 中。接着,遍历所有子控件,将它们测量并按规则排列在面板中,同时更新列高和面板的大小。
  • AddChild 方法向面板中添加子控件。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Controls;
using System.Windows;

namespace WPFDevelopers.Controls
{
    public class WaterfallPanel : VirtualizingPanel
    {
        private List<double> columnHeights = new List<double>();
        protected override Size MeasureOverride(Size availableSize)
        {
            columnHeights.Clear();
            var panelDesiredSize = new Size(0, 0);
            columnHeights = new double[Columns].ToList();
            double currentX = 0;
            var width = availableSize.Width / Columns - (Columns * Spacing);
            for (int i = 0; i < InternalChildren.Count; i++)
            {
                var child = InternalChildren[i] as FrameworkElement;
                if (child == null)
                    continue;
                child.Measure(availableSize);
                child.Width = width;
                int columnIndex = i % Columns;
                double x = columnIndex != 0 ? currentX + Spacing : 0;
                double y = columnHeights[columnIndex];
                if (i >= Columns)
                    y = y + Spacing;
                var size = new Size(width, child.DesiredSize.Height);
                child.Arrange(new Rect(new Point(x, y), size));
                panelDesiredSize.Width = Math.Max(panelDesiredSize.Width, x + child.DesiredSize.Width);
                panelDesiredSize.Height = Math.Max(panelDesiredSize.Height, y + child.DesiredSize.Height);
                currentX = x + size.Width;
                if (currentX >= Width)
                    currentX = 0;
                columnHeights[columnIndex] += child.DesiredSize.Height + (i >= Columns ? Spacing : 0);
            }
            return panelDesiredSize;
        }

        public void AddChild(UIElement element)
        {
            Children.Add(element);
        }

        public int Columns
        {
            get { return (int)GetValue(ColumnsProperty); }
            set { SetValue(ColumnsProperty, value); }
        }

        public static readonly DependencyProperty ColumnsProperty =
            DependencyProperty.Register("Columns", typeof(int), typeof(WaterfallPanel), new PropertyMetadata(3));

        public double Spacing
        {
            get { return (double)GetValue(SpacingProperty); }
            set { SetValue(SpacingProperty, value); }
        }

        public static readonly DependencyProperty SpacingProperty =
            DependencyProperty.Register("Spacing", typeof(double), typeof(WaterfallPanel), new PropertyMetadata(5.0));
    }
}

2)示例(一)代码WaterfallPanelExample.xaml如下:

  <ScrollViewer>
      <wd:WaterfallPanel Width="750">
          <wd:WaterfallPanel.Resources>
              <Style TargetType="Border">
                  <Setter Property="CornerRadius" Value="10" />
                  <Setter Property="BorderBrush" Value="LightGray" />
                  <Setter Property="BorderThickness" Value="1" />
              </Style>
              <Style TargetType="ImageBrush">
                  <Setter Property="Stretch" Value="Fill" />
              </Style>
              <Style TargetType="TextBlock">
                  <Setter Property="Margin" Value="4,10" />
                  <Setter Property="Foreground" Value="White" />
              </Style>
              <Style x:Key="BorderContent" TargetType="Border">
                  <Setter Property="Height" Value="40" />
                  <Setter Property="CornerRadius" Value="10,10,0,0" />
                  <Setter Property="VerticalAlignment" Value="Top" />
                  <Setter Property="Background">
                      <Setter.Value>
                          <LinearGradientBrush Opacity=".3" StartPoint="0,.5" EndPoint="0,1">
                              <GradientStop Offset="0" Color="DimGray" />
                              <GradientStop Offset="0.9" Color="Gray" />
                              <GradientStop Offset="1" Color="Transparent" />
                          </LinearGradientBrush>
                      </Setter.Value>
                  </Setter>
              </Style>
          </wd:WaterfallPanel.Resources>
          <Border Height="340">
              <Border.Background>
                  <ImageBrush ImageSource="http://tse2-mm.cn.bing.net/th/id/OIP-C.WVAYTzW5VMZgAErg-y6EgwAAAA" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="WVAYTzW5VMZgAErg" />
              </Border>
          </Border>
          <Border Height="300">
              <Border.Background>
                  <ImageBrush ImageSource="http://tse1-mm.cn.bing.net/th/id/OIP-C.e51iwDiqzatju6Bf50lJ2QHaMW" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="e51iwDiqzatju6Bf50lJ2QHaMW" />
              </Border>
          </Border>
          <Border Height="280">
              <Border.Background>
                  <ImageBrush ImageSource="http://tse1-mm.cn.bing.net/th/id/OIP-C.dB2fWdfqfr8w3sP7wiboHgHaNK" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="dB2fWdfqfr8w3sP7wiboHgHaNK" />
              </Border>
          </Border>
          <Border Height="350">
              <Border.Background>
                  <ImageBrush ImageSource="http://tse4-mm.cn.bing.net/th/id/OIP-C.IzGLt2NgGhakuvbk008FOwHaK9" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="IzGLt2NgGhakuvbk008FOwHaK9" />
              </Border>
          </Border>
          <Border Height="400">
              <Border.Background>
                  <ImageBrush ImageSource="http://pic4.zhimg.com/v2-6233e57a364dcb3b6c5f066f8b30dab4_r.jpg" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="6233e57a364dcb3b6c5f066f8b30dab4_r" />
              </Border>
          </Border>
          <Border Height="240">
              <Border.Background>
                  <ImageBrush ImageSource="http://tse1-mm.cn.bing.net/th/id/OIP-C.ivs2k5Q7Zx7WRZVuSDUJqQHaJ4" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="ivs2k5Q7Zx7WRZVuSDUJqQHaJ4" />
              </Border>
          </Border>
          <Border Height="290">
              <Border.Background>
                  <ImageBrush ImageSource="http://tse3-mm.cn.bing.net/th/id/OIP-C.sTVQljOS9ntgkUyvDXk68AHaKe" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="sTVQljOS9ntgkUyvDXk68AHaKe" />
              </Border>
          </Border>
          <Border Height="207">
              <Border.Background>
                  <ImageBrush ImageSource="http://tse2-mm.cn.bing.net/th/id/OIP-C.caVFPs_YGiHH-7vOpQ7GqwHaHY" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="7vOpQ7GqwHaHY" />
              </Border>
          </Border>
          <Border Height="200">
              <Border.Background>
                  <ImageBrush ImageSource="http://tse2-mm.cn.bing.net/th/id/OIP-C.T_Zi1o-AYSCp4c00D_zCVAHaHa" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="AYSCp4c00D_zCVAHaHa" />
              </Border>
          </Border>
          <Border Height="220">
              <Border.Background>
                  <ImageBrush ImageSource="http://tse2-mm.cn.bing.net/th/id/OIP-C.-EGv7Ycl5Zu46_YIGjNuDgHaH4" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="EGv7Ycl5Zu46_YIGjNuDgHaH4" />
              </Border>
          </Border>
          <Border Height="200">
              <Border.Background>
                  <ImageBrush ImageSource="http://tse4-mm.cn.bing.net/th/id/OIP-C.TQ1f0BMQ7Bo7PuRKnCJAMAHaHa" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="TQ1f0BMQ7Bo7PuRKnCJAMAHaHa" />
              </Border>
          </Border>
          <Border Height="450">
              <Border.Background>
                  <ImageBrush ImageSource="http://img.zcool.cn/community/01493f5d11d9cca801205e4b24e764.jpg" />
              </Border.Background>
              <Border Style="{StaticResource BorderContent}">
                  <TextBlock Text="01493f5d11d9cca801205e4b24e764" />
              </Border>
          </Border>
      </wd:WaterfallPanel>
  </ScrollViewer>

3)示例(二)后台添加代码WaterfallPanelExample.xaml.cs 如下:

var ran = new Random();
for (int i = 0; i < 1000; i++)
{
    var btn = new Button { Content = i.ToString(), Height = (double)ran.Next(100, 1000) };
    MyWaterfallPanel.AddChild(btn);
}

效果图

到此这篇关于基于WPF实现瀑布流控件的文章就介绍到这了,更多相关WPF瀑布流控件内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#深度优先搜索算法

    C#深度优先搜索算法

    这篇文章主要介绍了C#深度优先搜索算法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • 使用代理模式来进行C#设计模式开发的基础教程

    使用代理模式来进行C#设计模式开发的基础教程

    这篇文章主要介绍了使用代理模式来进行C#设计模式开发的基础教程,代理模式主张在客户端和目标对象中间建立中介来降低程序设计的耦合度,需要的朋友可以参考下
    2016-02-02
  • 使用Deflate算法对文件进行压缩与解压缩的方法详解

    使用Deflate算法对文件进行压缩与解压缩的方法详解

    本篇文章是对使用Deflate算法对文件进行压缩和解压缩的方法进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • C#读写xml文件方法总结(超详细!)

    C#读写xml文件方法总结(超详细!)

    项目中用到关于xml文件读写操,所以下面这篇文章主要给大家介绍了关于C#读写xml文件方法的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2023-02-02
  • C# 泛型的简单理解(安全、集合、方法、约束、继承)分享

    C# 泛型的简单理解(安全、集合、方法、约束、继承)分享

    这篇文章介绍了C# 泛型的简单理解(安全、集合、方法、约束、继承),有需要的朋友可以参考一下
    2013-10-10
  • C# Onnx实现特征匹配DeDoDe检测

    C# Onnx实现特征匹配DeDoDe检测

    这篇文章主要为大家详细介绍了C# Onnx如何实现特征匹配DeDoDe检测,文中的示例代码讲解详细,具有一定的借鉴价值,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-11-11
  • C#实现简单订单管理程序

    C#实现简单订单管理程序

    这篇文章主要为大家详细介绍了C#实现简单订单管理程序,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-05-05
  • jQuery uploadify在谷歌和火狐浏览器上传失败的解决方案

    jQuery uploadify在谷歌和火狐浏览器上传失败的解决方案

    jquery.uploadify插件是一个基于jquery来实现上传的,这个插件很好用,每一次向后台发送数据流请求时,ie会自动把本地cookie存储捆绑在一起发送给服务器。但firefox、chrome不会这样做,他们会认为这样不安全,下面介绍下jQuery uploadify上传失败的解决方案
    2015-08-08
  • C#基本打印事件用法实例

    C#基本打印事件用法实例

    这篇文章主要介绍了C#基本打印事件用法,实例分析了C#中print打印及DrawString文本字符串绘制等相关技巧,需要的朋友可以参考下
    2015-06-06
  • C#操作CSV文件的详细教程

    C#操作CSV文件的详细教程

    文章详细介绍了CSV文件的格式、读取和写入多种方式,包括使用StreamReader、TextFieldParser、CsvHelper库等,同时,还讨论了处理特殊字符、将CSV数据映射到对象以及注意事项,如文件路径和数据类型转换,并提到了性能优化的方法,需要的朋友可以参考下
    2026-01-01

最新评论