FlowLayoutPanel 中的多行控件居中

2023-11-27

我正在尝试制作一个可以托管动态添加控件的面板。有两个注意事项:

  • 将会有很多控件,因此面板应在达到其宽度限制并垂直滚动时将元素包装到新行中。
  • 控件的大小可以改变,这会改变元素的数量
    可以放入一行。

我看到了一些将动态控件集中在表单中的提议解决方案,但由于以下原因而拒绝了这些解决方案:

  • TableLayoutPanel - 我使用它时遇到的主要问题是事件 元素生长并且必须从 3-2 网格转变为 2-4,如 TableLayoutPanel 似乎不能很好地处理这些。
  • AutoSize FlowLayoutPanel 可以在其内部放大和缩小 TableLayoutControl - 这个解决方案的主要问题是它 仅在表单内居中一行,一旦换行到新行, 元素开始向右对齐。我想我可以动态地 将新的 FlowLayoutPanel 添加到 TableLayoutControl 的新行,然后 我有一个与第一个场景类似的问题,我需要手动 如果元素大小增大/缩小,则在行之间重新分配元素。

我想知道我是否缺少一些可以帮助我处理增长/收缩事件而不创建我自己的 TableLayoutPanel 变体的功能?

Edit:
以下是功能草案:

  • A - 面板居中的两个元素
  • B - 添加第三个元素,所有三个元素均居中
  • C - 添加第四个元素,包装到新行并居中
  • D - 元素放大,现在包裹在第二个元素上,居中

Draft


这是一个重现您所描述的行为的示例。
它使用托管多个 FlowLayoutPanel 的 TableLayoutPanel。

一个重要的细节是子 FlowLayoutPanel 的锚定:它们需要锚定到上下:这会导致面板位于 TableLayoutPanel 行的中心。

请注意,在 Form 构造函数中,其中之一RowStyles已移除。这一点也非常重要:TLP(这是一个非常古怪的家伙),即使你只有一行(或一列,同样的事情),也会保留 2RowStyles。第二种样式将应用于您添加的第一行;只针对第一个,而不是其他:这可能会搞乱布局。

另一个异常是,它没有提供删除行的方法,所以我做了一个。它功能齐全,但很简陋,需要扩展,包括进一步验证。

请参阅有关当前功能的图形示例。如果您在实施其他方面需要帮助,请发表评论。


要构建此控件,请将以下控件添加到表单(此处称为FLPTest1):

  1. 添加一个Panel,设置Dock.Bottom。右键单击并SendToBack(),
  2. Add a TableLayoutPanel (here, called tlp1), set:
    • AutoScroll = true, AutoSize = true,
    • AutoSizeMode = GrowAndShrink, Dock.Fill
    • 保留 1 列,设置为 AutoSize,保留 1 行,设置为 AutoSize
  3. Add a FlowLayoutPanel (here, called flp1), positioned inside the TableLayoutPanel. It's not actually necessary, just for this sample code
    • 将其锚点设置为Top, Bottom <=这是!important,如果没有它,布局将无法正常工作:它允许将FLP在 - 的里面TLP Row,
    • AutoSize = true, AutoSizeMode = GrowAndShrink
  4. 添加一个按钮(称为btnAddControl)
  5. 添加第二个按钮(称为btnRemoveControl)
  6. 添加一个复选框(称为chkRandom)
  7. 将代码粘贴到表单的代码文件中

TableLayoutPanel Flow

using System.Drawing;
using System.Linq;
using System.Windows.Forms;


public partial class TLPTest1 : Form
{
    public TLPTest1()
    {
        InitializeComponent();
        tlp1.RowStyles.RemoveAt(1);
    }

    private void TLPTest1_Load(object sender, EventArgs e)
    {
        PictureBox pBox = new PictureBox() {
            Anchor = AnchorStyles.None,
            BackColor = Color.Orange,
            MinimumSize = new Size(125, 125),
            Size = new Size(125, 125),
        };
        flp1.Controls.Add(pBox);
        tlp1.Controls.Add(flp1);
    }

    Random rnd = new Random();
    Size[] sizes = new Size[] { new Size(75, 75), new Size(100, 100), new Size(125, 125)};
    Color[] colors = new Color[] { Color.Red, Color.LightGreen, Color.YellowGreen, Color.SteelBlue };
    Control selectedObject = null;

    private void btnAddControl_Click(object sender, EventArgs e)
    {
        Size size = new Size(125, 125);
        if (chkRandom.Checked) size = sizes[rnd.Next(sizes.Length)];
        
        var pBox = new PictureBox() {
            Anchor = AnchorStyles.None,
            BackColor = colors[rnd.Next(colors.Length)],
            MinimumSize = size,
            Size = size
        };

        bool drawborder = false;
        // Just for testing - use standard delegates instead of Lambdas in real code
        pBox.MouseEnter += (s, evt) => { drawborder = true;  pBox.Invalidate(); };
        pBox.MouseLeave += (s, evt) => { drawborder = false; pBox.Invalidate(); };
        pBox.MouseDown += (s, evt) => { selectedObject = pBox;  pBox.Invalidate(); };
        pBox.Paint += (s, evt) => { if (drawborder) {
            ControlPaint.DrawBorder(evt.Graphics, pBox.ClientRectangle, 
                                    Color.White, ButtonBorderStyle.Solid);
            }
        };

        var ctl = tlp1.GetControlFromPosition(0, tlp1.RowCount - 1);
        int overallWith = ctl.Controls.OfType<Control>().Sum(c => c.Width + c.Margin.Left + c.Margin.Right);
        overallWith += (ctl.Margin.Right + ctl.Margin.Left);

        if ((overallWith + pBox.Size.Width + pBox.Margin.Left + pBox.Margin.Right) >= tlp1.Width) {
            var flp = new FlowLayoutPanel() {
                Anchor = AnchorStyles.Top | AnchorStyles.Bottom,
                AutoSize = true,
                AutoSizeMode = AutoSizeMode.GrowAndShrink,
            };

            flp.Controls.Add(pBox);

            tlp1.SuspendLayout();
            tlp1.RowCount += 1;
            tlp1.Controls.Add(flp, 0, tlp1.RowCount - 1);
            tlp1.ResumeLayout(true);
        }
        else {
            ctl.Controls.Add(pBox);
        }
    }

    private void btnRemoveControl_Click(object sender, EventArgs e)
    {
        if (selectedObject is null) return;
        Control parent = selectedObject.Parent;
        selectedObject.Dispose();

        if (parent?.Controls.Count == 0) {
            TLPRemoveRow(tlp1, parent);
            parent.Dispose();
        }
    }

    private void TLPRemoveRow(TableLayoutPanel tlp, Control control)
    {
        int ctlPosition = tlp.GetRow(control);
        if (ctlPosition < tlp.RowCount - 1) {
            for (int i = ctlPosition; i < tlp.RowCount - 1; i++) {
                tlp.SetRow(tlp.GetControlFromPosition(0, i + 1), i);
            }
        }
        tlp.RowCount -= 1;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

FlowLayoutPanel 中的多行控件居中 的相关文章

  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 如何从本机 C(++) DLL 调用 .NET (C#) 代码?

    我有一个 C app exe 和一个 C my dll my dll NET 项目链接到本机 C DLL mynat dll 外部 C DLL 接口 并且从 C 调用 C DLL 可以正常工作 通过使用 DllImport mynat dl
  • 从经典 ASP 调用 .Net C# DLL 方法

    我正在开发一个经典的 asp 项目 该项目需要将字符串发送到 DLL DLL 会将其序列化并发送到 Zebra 热敏打印机 我已经构建了我的 DLL 并使用它注册了regasm其次是 代码库这使得 IIS 能够识别它 虽然我可以设置我的对象
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 对类 static constexpr 结构的未定义引用,g++ 与 clang

    这是我的代码 a cp p struct int2 int x y struct Foo static constexpr int bar1 1 static constexpr int2 bar2 1 2 int foo1 return
  • 重载 (c)begin/(c)end

    我试图超载 c begin c end类的函数 以便能够调用 C 11 基于范围的 for 循环 它在大多数情况下都有效 但我无法理解和解决其中一个问题 for auto const point fProjectData gt getPoi
  • 方程“a + bx = c + dy”的积分解

    在等式中a bx c dy 所有变量都是整数 a b c and d是已知的 我如何找到整体解决方案x and y 如果我的想法是正确的 将会有无限多个解 由最小公倍数分隔b and d 但我只需要一个解决方案 我可以计算其余的 这是一个例
  • C# 列表通用扩展方法与非通用扩展方法

    这是一个简单的问题 我希望 集合类中有通用和非通用方法 例如List
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • VB.NET 中的静态方法实现

    我很困惑Static在 VB NET 中的实现 在 C 中 我们可以创建静态类和静态方法来为我们的应用程序编写实用方法 现在 VB NET 让我们创建Module代替静态类 如果我们在模块中创建一个方法 默认情况下它会变成静态的 但在我的应
  • 两个类可以使用 C++ 互相查看吗?

    所以我有一个 A 类 我想在其中调用一些 B 类函数 所以我包括 b h 但是 在 B 类中 我想调用 A 类函数 如果我包含 a h 它最终会陷入无限循环 对吗 我能做什么呢 仅将成员函数声明放在头文件 h 中 并将成员函数定义放在实现文
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • 复制目录下所有文件

    如何将一个目录中的所有内容复制到另一个目录而不循环遍历每个文件 你不能 两者都不Directory http msdn microsoft com en us library system io directory aspx nor Dir
  • 当文件流没有新数据时如何防止fgets阻塞

    我有一个popen 执行的函数tail f sometextfile 只要文件流中有数据显然我就可以通过fgets 现在 如果没有新数据来自尾部 fgets 挂起 我试过ferror and feof 无济于事 我怎样才能确定fgets 当
  • DotNetZip:如何提取文件,但忽略zip文件中的路径?

    尝试将文件提取到给定文件夹 忽略 zip 文件中的路径 但似乎没有办法 考虑到其中实现的所有其他好东西 这似乎是一个相当基本的要求 我缺少什么 代码是 using Ionic Zip ZipFile zf Ionic Zip ZipFile
  • 现代编译器是否优化乘以 1 和 -1

    如果我写 template
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat

随机推荐

  • invalid_client 用于使用苹果登录

    我试图实现的目标 iOS 客户端向后端发送 JWT 令牌 后端 Java 调用https appleid apple com auth token验证令牌 到目前为止我所拥有的 拨打 Apple 验证电话 restTemplate new
  • 如何授权一组控制器而不在每个控制器上添加注释?

    我有一组控制器 每个控制器用于每种授权类型 例如 A 类授权将具有一组控制器 每个控制器都需要 A 类授权 有没有办法放置一个 Authorize Role Class A 某处的属性将适用于每个控制器 而不必用相同的属性装饰每个控制器 您
  • 为什么/什么时候适合重写 ToString?

    我正在学习 C 我想知道重写的意义和好处是什么ToString可能是这样 如下例所示 是否可以通过某种更简单的方式来完成此操作 使用通用方法而不需要覆盖 public string GetToStringItemsHeadings get
  • 如何将 PHP 应用程序限制在它们自己的目录和它们自己的 php.ini 中?

    我在 Mac 上运行多个 PHP 应用程序 运行 OS X 10 5 6 Apache 2 PHP 5 我为每个项目设置了子域 每个子域的主机文件条目以及 Apache 配置中的虚拟目录块 所以 project1 localhost 转到
  • SMTP 服务器需要安全连接或客户端未经过身份验证

    SMTP 服务器需要安全连接 或者客户端未经过身份验证 服务器响应为 5 7 0 必须首先发出 STARTTLS 命令 k12sm3795394wby 16 描述 当前Web请求执行期间发生未处理的异常 请查看堆栈跟踪以获取有关错误及其在代
  • 强制 64 位 jvm 到 32 位 jvm?

    有人可以给我关于强制 64 位 jvm 作为 32 位 jvm 运行的想法吗 我需要编写一个用于蓝牙连接的 jse 桌面应用程序 为此 我需要实现 Bluecove jar 它只有 32 位文件 所以我在 eclipse pulsar 的
  • 不支持关键字:“版本”

    我有一个在 VS2010 中作为 WinForms 项目编写的项目 我不是在 VS2012 中将其作为 WPF 项目编写 我有一个引用的DLL DailyReport 里面DailyReport是一个方法叫做GetUniqueDates 它
  • 转换使用反射创建的泛型类型实例

    我正在使用反射创建泛型类型的实例 public interface IModelBuilder
  • 如何找到空的 git 提交?

    我可以使用什么命令来查找 git 存储库中的空提交 即将被删除的提交git filter branch prune empty 您需要排除无父提交和合并提交 然后查看哪些提交与其父提交具有相同的树 for sha in git rev li
  • 如果线程启动 Executor,则无法从 Future 和 SwingWorker 获取 ArrayIndexOutOfBoundsException

    我通过使用 Executor 对 SwingWorker 进行多线程处理 并且错误地从 Vector 中识别出错误的元素 看起来像此代码相当忽略了 Vector 中不存在的元素 我的问题 gt 如何 可能以某种方式捕获此异常 简单输出 ru
  • 为什么仅采用 AVX 的处理器在许多 SIMD 算法方面的性能优于 AVX2 处理器?

    我一直在研究 C 和 C 中 SIMD 算法的优势 发现在许多情况下 在 AVX 处理器上使用 128 位寄存器比在具有 AVX2 的处理器上使用 256 位寄存器提供更好的改进 但我不这么认为 不明白为什么 我所说的改进是指在同一台机器上
  • PHP - foreach 因空合并运算符而丢失引用

    问题一 我觉得 在以下情况下将不执行任何操作 a 1 2 foreach a as v v var dump a But why array 2 0 gt int 1 1 gt int 2 问题2 这更奇怪了 foreach a 1 2 a
  • 如何将视频(从 getUserMedia)发送到 Node.js 服务器?

    我正在寻找构建一个聊天 直播应用程序 视频 文本聊天 我目前还没有确定一种方法 但我正在推进一种方法 但我陷入了困境 我正在尝试使用 getUserMedia 获取视频流 并通过 Socket io 将其发送到我的 Node js 服务器
  • ggplot2 多个 stat_smooth:更改颜色和线型

    我无法使用多个平滑器更改当前绘图的颜色和线型 stat smooth 这里是数据结构的概述 serviceInstanceName timestamp value 1 DE1Service utilityPredicted 2014 02
  • 如何使用 Volley 网络请求队列?

    I add 对我的 Volley 请求队列的新网络调用 我已按照建议将其创建为单例 但我总是立刻 start 这些网络调用 这始终作为活动或片段中的操作来完成 The add方法甚至不能链接到start方法 比如 add new volle
  • 数据行到字符串到数组问题

    我遇到了一个非常奇怪的问题 我有一个填充有一堆行的对象 我可以很好地访问它们 但我需要附加一个 点 到其中的每个值 因此我最终使用 foreach 循环将每个记录转换为字符串并添加一个 修剪值后 然而现在的问题是 我想将每一行 并且这些行只
  • 对于包括设置在内的小型 C 程序,合理的最小汇编指令数是多少?

    我正在尝试生成尽可能小的 C 程序 以查看通过运行它执行了多少条指令 我禁用了库的使用并禁用了 vdso 然而 根据 perf stat 我的 C 程序 gdb 说是 7 条汇编指令 最终执行了 17k 条指令 这是用于设置程序的正常指令量
  • 如何使用命令行将“其他链接器标志”添加到 xcode 项目?

    我正在尝试自动化 xcode 项目的构建过程 问题是我需要在构建项目时添加 其他链接器标志 我不能只是手动将其添加到项目构建设置中 我必须使用命令行来完成 也许我可以以某种方式编辑项目文件或配置文件 只要可以作为脚本运行 任何选项都是好的
  • 如何访问自定义元素的主机

    我有一个自定义元素 它本身承载一个自定义元素
  • FlowLayoutPanel 中的多行控件居中

    我正在尝试制作一个可以托管动态添加控件的面板 有两个注意事项 将会有很多控件 因此面板应在达到其宽度限制并垂直滚动时将元素包装到新行中 控件的大小可以改变 这会改变元素的数量可以放入一行 我看到了一些将动态控件集中在表单中的提议解决方案 但