如何避免Windows Forms单选按钮容器自动分组

7

背景

在.NET Windows Forms (2.0) 中,单选按钮会自动按其容器控件进行分组,无论是 Form、Panel 还是 GroupBox。

这意味着当您选择一个单选按钮时,同一容器中的其他单选按钮会自动变为未选中状态。

现在,考虑以下表单布局:

MUST HAVE  NICE TO HAVE  DESCRIPTION
---------  ------------  -----------------------------------------------
   [ ]          [ ]      The gizmo works
   [ ]          [ ]      The gizmo works beautifully
   [ ]          [ ]      The gizmo works amazingly and makes you breakfast
   [ ]          [ ]      The gizmo comes with a pony
  • 每个'[ ]'都是一个单选按钮。
  • 用户被要求在第一列中选择必填答案,在第二列中选择可选的(期望的,最佳情况下的)答案。

正如您所看到的,单选按钮应该按列分组:选择其中一个单选按钮应清除该列的其余部分,但不应对另一列产生影响。

问题

基本上,问题是这是一个动态生成的表单。

  • 布局中的行数是动态的,并且从可配置的表单定义中加载。
  • 描述文本直到运行时才知道,长度差异很大(有些可能只有几个单词,而其他一些则有十几行)。
  • 布局不能重新设计。这来自于(非技术性)用户对已使用多年的纸质版本此表单的熟悉程度。此表单也将被打印,即使我更改了表单的输入系统,这也意味着需要使用“旧”布局编写另一个用于打印的版本。

我尝试过但未成功的方法

我首先尝试使用三个面板之一实现这个动态生成的布局,因此自动单选按钮分组将正常工作。它确实如此。

但是与单选按钮及其文本之间的水平对齐相关的布局问题让我很困扰。文本的大小直到运行时才知道,文本行可能会换行(有时每个项目都会多次换行)。有时它对齐得很好,有时则没有。我即将开始调试,但我在思考也许改变这个三面板实现是更好的选择。

我正在尝试做什么

我想通过使用一个具有三列的TableLayoutPanel重新设计布局,以简化与对齐相关的问题,但这意味着我不能使用自动单选按钮容器分组“功能”。

编辑:

如Gerrie建议的那样,其他布局选项是将每行实现为用户控件并使用流式布局面板。

这意味着,再次,我可能希望使用控件进行布局,但不用于单选按钮分组。

我需要垂直单选按钮组,尽管使用了水平用户控件

/编辑

我要求的是

我需要关于如何手动控制单选按钮分组的指针和建议。如果需要,我真的不介意子类化RadioButton类。

具体来说,是否有任何“规范”或已知的方法可以子类化“RadioButton”,或者走到Win32 API,以便每次通过使用鼠标,键盘Enter,空格键和我可能不知道选择它们的任何其他方式来检查控件时,我都可以捕获事件并手动更新表单中的每个其他控件的状态,并以已知的方式“停用”自动分组功能?我担心实现也与容器相关,我可能还被迫子类化Panel?
在Windows Forms中,分组“魔法”是如何工作的?
我在谷歌上找到的所有解决方案都是基于某种方式使用容器进行分组的自定义单选按钮组或“单选按钮列表”。可以避免使用容器吗?如果可以,怎么做?。
2个回答

6
我找到的一个“临时”解决方案(即:混乱的hack)是将每个单选按钮放在自己的小面板中。因此,它们之间根本没有任何分组。我正在监听每个按钮checked事件,并相应地更新适当的按钮。
我仍然认为拥有那么多面板是过度的,如果有人有更简洁的解决方案,我很想听听。
(好吧,抱歉回答了自己的问题。你知道当你花时间解释某些事情时,你会以不同的方式看待这个问题。)

如果您选择这个解决方案,那么现在是创建一个自己的单选按钮的好时机,它不必在面板中。并且当您在进行此操作时,添加一个可选属性GroupID,在切换时将其发送回来。 - Stefan
再次感谢您的帮助,Stefan。顺便说一下,我已经创建了一个IndependentRadioButton类,但是还没有想到在那里添加GroupId属性。听起来很合适。 - Sergio Acosta
@nobugz:当用户勾选另一个复选框时,文本框会变为未勾选状态吗?不是,这就是单选按钮的作用。谢谢。 - Sergio Acosta
我不会称这为一个混乱的黑科技,我会称之为正确的解决方案。每个面板应包含两个单选按钮和文本,因此每个面板代表一行。然后使每个面板交替变色(如灰色,略浅的灰色),以便用户可以视觉上看到什么与什么分组。 - BlueRaja - Danny Pflughoeft

1

我会选择一个简单明了的解决方案。例如,一个自定义控件代表一行(两个单选按钮和一个标签)。

编辑:好的,我现在理解你的要求了。你不能只有两个单选按钮集合吗:列A中的单选按钮和列B中的单选按钮?

当你的表单被绘制时,将它们添加到两个List<RadioButton>或其他对象中,并将它们绑定到两个不同的事件:columnARBChecked、columnBRBChecked。当其中一个事件触发时,您可以调用一些逻辑来检查/取消选中其余的单选按钮。


那当然可以使用该方法来布局,而不是使用 TableLayoutPanel。但这种解决方案的问题在于,用户控件内部的按钮仍然会被分组在用户控件内部。因此,我将拥有与用户控件实例相同数量的组,而不是 2 组(每列一个)。 - Sergio Acosta
抱歉,我不完全理解您的需求。您想要水平分组对吗?为什么还要垂直面板呢?您为什么不能只是循环遍历自定义控件集合并读取哪个单选按钮被选中了呢? - Gerrie Schenck
抱歉,我会编辑问题以澄清实际上我需要的不是水平分组(这是默认情况),而是垂直分组。谢谢。 - Sergio Acosta
问题不在于知道哪些控件被选中了。问题在于如果这些单选按钮在同一个容器中,当用户选中其中一个时,winforms会自动取消选中其他单选按钮。我不希望发生这种情况。 - Sergio Acosta
关于您的编辑:是的,那就是我计划要做的事情。问题在于如何避免WinForms管理选中值。这就是为什么我想到了我的临时解决方案,即将每个按钮添加到它们自己的面板中。目前更一般的问题是如何禁用WinForms自动分组单选按钮。 - Sergio Acosta

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接