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 中的多行控件居中 的相关文章

  • ZedGraph 缩放和调整大小

    当我绘制图形 放大和缩小并重新绘制图形时 图形的位置不会改变 我想要做的是 每当重新绘制数据时 视图都会更改以查看所有图形数据 如果您在重绘之前放大或缩小 这似乎会被禁用 Thanks 设置属性 IsZoomOnMouseCenter对于控
  • 当“”可以分配给std::string时,为什么有“clear”方法?

    一个可以用string clear函数清空字符串 也可以使用空双引号 来执行此操作 有什么不同 当您分配一个空字符串时 编译器必须在数据部分存储一个空的 C 字符串 并创建代码以将指向它的指针传递给赋值运算符 然后 赋值运算符必须从数据部分
  • C++17 中带有 noexcept 的 std::function

    在 C 17 中noexcept 已添加到类型系统中 http www open std org jtc1 sc22 wg21 docs papers 2015 p0012r1 html void r1 void f noexcept f
  • 具有长期运行对象上下文的实体框架

    我对 WinForms 我敢说 WPF 中的 Linq to SQL 的主要烦恼之一是缺乏对长时间运行的数据上下文的支持 请参阅here http blogs msdn com dinesh kulkarni archive 2008 04
  • 增加超时时间

    我必须增加超时时间 以下是我的代码 Private Function GetConnectionInstance As SqlConnection Dim objConn As SqlConnection Dim strConnection
  • 如何获取任意类型的默认值

    在 C 中我可以写这样的东西 class AnyThing
  • 使用 boost::iterator_facade<>

    我有一个链表结构 struct SomeLinkedList const char bar int lots of interesting stuff in here DWORD foo SomeLinkedList pNext 它是现有
  • F# 内联如何工作?

    对于 F 我的理解是您可以使用 inline 关键字在调用站点执行类型专门化 那是 val inline a gt b gt c when a or b static member a b gt c 约束条件是 a or b必须有一个静态成
  • 了解 MVC-5 身份

    我创建了一个新的ASP NET MVC 5申请与Individual User Accounts然后更新了所有的Nuget packages在解决方案中 现在我尝试遵循一些教程中显示的一些指南 但遇到了一些问题 第一个是一个名为Applic
  • 让 GCC/Clang 使用 CMOV

    我有一个简单的标记值联合 这些值可以是int64 ts or doubles 我正在对这些联合进行加法 但需要注意的是 如果两个参数都代表int64 t值 那么结果也应该有一个int64 t value 这是代码 include
  • 使用 MapViewOfFile 有什么限制吗?

    我正在尝试将内存映射文件用作 hFile CreateFile State Path GENERIC READ FILE SHARE READ FILE SHARE WRITE 0 OPEN EXISTING FILE FLAG SEQUE
  • DLL 中的 XP 风格组合框

    我需要使用 C 和 WIN32 API 无 MFC 在 DLL 中创建 XP 风格的组合框 我设法在 DLL 中创建控件 不是以 XP 风格 我设法在带有清单的 exe 中创建 XP 样式组合框 但它在 DLL 中不起作用 为了让您的 DL
  • 如何在 C# 中通过 JavaScript 回调运行 QUnit 测试并获取测试结果?

    在我的几个项目中 我使用 MVC 模式将代码 关注点 分为 3 层 模型层和控制层都在 C 上运行 因此我使用 MSTest 或 NUnit 等测试框架来验证这些层的功能需求 对于视图层 我使用 QUnit 来测试 JavaScript 文
  • C语言中如何将整数转换为字符? [复制]

    这个问题在这里已经有答案了 C语言中如何将整数转换为字符 C 中的字符已经是数字 字符的 ASCII 代码 无需转换 如果要将数字转换为相应的字符 只需添加 0 即可 c i 0 0 是 ASCii 表中的一个字符
  • MPI_Gatherv:根数组中收到的垃圾值

    我正在尝试实施MPI Gatherv函数于C 根据我的程序 包括 root 在内的每个进程都应该创建一个大小等于 进程的等级 1 这将在所有单元格中保持进程的等级 然后这个本地数组被收集到根的 rcv array 中 不知何故 我得到了垃圾
  • C# 记录类型:记录子类之间的相等比较

    给定父记录类型 public record Foo string Value 和两个记录子类Bar and Bee我想知道是否可以实施Equals在基类中 因此 Foo Bar 或 Bee 的实例都被考虑equal基于Value 两者都与E
  • 在 C++ 中将大型数据向量写入/读取到二进制文件

    我有一个 C 程序 它通过将 ascii 文件中的网格人口数据读取到大型 8640x3432 元素双精度向量中来计算给定半径内的人口 将 ascii 数据读入向量大约需要 30 秒 循环每列和每行 而程序的其余部分只需要几秒钟 我被要求通过
  • 没有运算符“<<”与这些操作数匹配[重复]

    这个问题在这里已经有答案了 不知道发生了什么事 我查看了与此问题类似的其他帖子 但到目前为止没有解决方案有帮助 这是带有错误部分注释的代码 在某一时刻 它说 不起作用 而在代码的其余部分中 它说 include
  • Selenium WebDriver 在按钮单击事件上无法正常工作。这里有什么问题呢?

    I am using following code to scrape data from a website I have following interface 这是 HTML div class es content div
  • “保留供任何使用”是什么意思?

    注意 这是一个c questions tagged c问题 虽然我补充说c questions tagged c 2b 2b如果某些 C 专家可以提供 C 使用与 C 不同的措辞的基本原理或历史原因 在 C 标准库规范中 我们有这个规范文本

随机推荐

  • 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 中的多行控件居中

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