【问题标题】:How to cope with different lengths of labels– dynamic layout如何应对不同长度的标签——动态布局
【发布时间】:2009-07-16 18:36:15
【问题描述】:

我必须启用 winforms 应用程序中的所有文本来替换;它是一个旧应用程序,正在“维护”中。该应用程序是在 .NET v1.1 中编写的,其后续部分是在 .NET v2 中编写的,因此它不使用任何布局控件。

我遇到的问题是,当字符串比默认字符串长时,我需要让 UI 应对。但是,由于风险,我不希望对代码进行大量更改。

在过去,我发现简单的更改,例如向窗体添加面板并将当前控件拖到窗体上会丢失事件连接等。由于 WinForms 设计器移动代码的方式,它非常很难使用 DIFF 来发现此类问题。所以希望尽可能避免对控制树进行任何更改。

所以我正在寻找某种布局管理器,我可以将其添加到表单中而无需更改其余代码(或控制树)——任何理想?

我应该考虑其他任何选项吗?

(替换字符串的人不具备自己重新排列控件的技能;这也是维护的噩梦,因为标签可能需要为每个客户提供不同的值)

(回答说“如果我是你,我不会从这里开始”)


有人知道控制树外部的布局管理器吗?例如,我可以将它指向一个表单,它会接管控件的布局,而不必使所有控件成为布局管理器的子级。


see also this thread on the msdn Forums.

【问题讨论】:

  • “过去我发现简单的更改,例如向表单添加面板并将当前控件拖到它上面已经失去了事件连接等” - 你确定你从一个父母到另一个父母还是你剪切/粘贴?拖动不会破坏事件处理程序订阅,但剪切/粘贴肯定会导致这种情况。

标签: winforms layout internationalization


【解决方案1】:

我在布局管理器方面没有太多经验,而且我也不是真正的 UI 设计师,所以我很犹豫是否要回复,但看到似乎没有其他人,我插播了我的想法。

如果您唯一的问题是您不相信设计师会进行剪切和粘贴(即您相信设计师会重新调整大小),那么您可以手动完成该部分。

我过去所做的(不是因为我不信任设计师,而是因为我发现有时这样做更容易,)是:

(假设 C# 并向现有表单添加新面板)

1) 确保我有备份(通常在源代码管理中)

2) 将面板添加到表单中(通常与设计人员一起)

3) 关闭设计器并打开代码(xxx.cs 或 xxx.designer.cs)并找到将所有顶级控件添加到表单的位置,然后将它们全部移动(除了面板)以添加它们到面板。

即你从一些喜欢开始(希望有更有意义的名字)

this.form1.Controls.Add(this.label1);
this.form1.Controls.Add(this.textBox1);
etc.
this.form1.Controls.Add(this.panel1);

结束
this.panel1.Controls.Add(this.label1);
this.panel1.Controls.Add(this.textBox1);
etc 

this.form1.Controls.Add(this.panel1);

较新的表单可能使用类似的语法 this.form1.Controls.AddRange(新 System.Windows.Forms.Control[] { 这个.label1, this.TextBox1,
ETC this.panel1});

但主体是一样的。

4) 再做一次备份。 (这就是我希望我有一个源代码控制包,它允许我进行临时/私人/个人备份,而不会让其他人看到它。)

5) 在设计器中打开表单并检查所有控件是否都在那里。

6) 根据需要开始修改布局。

另外,我还没有尝试过,但如果您无法配置 Beyond Compare(请参阅 http://www.scootersoftware.com)来仅比较事件挂钩行(即包含 += 字符的那些),我会感到非常惊讶如果丢失,则更容易发现。

【讨论】:

    【解决方案2】:

    不幸的是,我知道没有这样的布局管理器。但是,我有一个建议,其中包括一些最小的(但我认为是安全的)代码更改。我在下面假设只有标签有问题,但这个概念也可以扩展到其他 WinForm 对象。我还假设所有的文本都是在设计器中最初设置的。

    首先,创建一个继承自 Label 的类。让我们称之为 SuperLabel 现在什么都不做。

    下一步,搜索并替换

    的所有实例

    新的 System.Windows.Forms.Label();

    新的超级标签();

    这是一个相当安全的改变。当然,您应该在进行过程中进行备份等,但是您的设计器和您的应用程序应该在此替换后 100% 像以前一样工作。毕竟,目前 SuperLabel 只是一个标签而已。

    最后,像下面的伪代码那样连接一些事件:

    公共类 SuperLabel : 标签 { 公共超级标签() { this.ParentChanged += new EventHandler(SuperLabel_ParentChanged); } 无效 SuperLabel_ParentChanged(对象发送者,EventArgs e) { // 这里有 Text 属性、Size 属性等可用 字符串 newText = GetNewTextFromSomeDictionary(Text); int lengthOfOriginalText = CalculateLengthOfOriginalText(); int lengthOfNewText = CalculateLengthOfNewText(); if (lengthOfNewText > lengthOfOriginalText) newText = CreateNewShorterTextSomehow(newText, lengthOfOriginalText); 文本 = 新文本; } // TODO: 在此处实现伪代码中的方法 ... }

    如您所见,这让您可以非常安全地在一个地方进行代码更改。在这个解决方案中,所有新文本都被添加到某个键值字典中,例如来自 xml 文件或诸如此类的东西。这样可以让替换字符串的人远离代码,避免在设计器中进行任何更改,并且可以处理太长的字符串。

    希望这会有所帮助!

    【讨论】:

    • 有趣的理想,因此+1,但是我需要为新的更长的字符串创造空间,而不是让它们更短。我不认为我们的新 Garman 用户会因为只看到他们一半的标签而感到高兴。我正在设置标签(和其他控件)文本,方法是从 Form 类的自定义子类中的 OnLoad() 覆盖中的字典中读取它们。我只是遍历完整的控制树,当用户更改语言时也会这样做。
    【解决方案3】:

    .Net Forms Resize 可能会有所帮助,它的网站说。

    可以很容易地实现 用 1 行代码设计表单

    我还没有详细了解它,它似乎主要是关于在分辨率变化时缩放控件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-08-22
      • 2023-04-02
      • 1970-01-01
      • 2014-07-03
      • 1970-01-01
      • 2023-03-26
      • 1970-01-01
      • 2021-08-19
      相关资源
      最近更新 更多