【问题标题】:Why does a control with Visible = false set early on in its life, ignore changes in bound properties?为什么在其生命早期设置 Visible = false 的控件会忽略绑定属性的变化?
【发布时间】:2020-04-22 06:28:33
【问题描述】:

我最近发现了一个似乎是 win 表单属性绑定的奇怪之处,如果一个控件在生命* 开始时是不可见的,那么该控件似乎不会看到绑定属性的变化。在这种情况下,我将标签的.Visible 属性绑定到应用程序设置中的Properties.Settings.Default.BooleanSetting(默认为False)。我还将一个复选框.Checked 绑定到相同的设置,其想法是切换复选框以选中会导致标签出现,而取消选中会导致标签消失。所有设置都在表单设计器中完成

这只有在应用程序启动时设置为 True 时才能可靠地工作。如果设置为 False,复选框将被取消选中,标签不可见但选中复选框不会显示标签。调试后发现设置的值是true,所以checkbox更新了,但是label的Visible属性还是false

其他绑定属性似乎没有问题如果标签最初可见; Enabled 可以绑定并且在复选框被切换时可靠地翻转状态,而不管设置的初始值如何。问题似乎特别是如果标签开始不可见 - 一个不可见的标签,其Enabled 属性绑定到该布尔值不会更改启用状态。

解决方法似乎是存储Properties.Settings.Default.BooleanSetting,在调用InitializeComponent() 之前将其设置为true,然后恢复它。在这种情况下,表单将显示,选中该框将显示不可见的标签

            var b = Properties.Settings.Default.FormatWithoutConfirmation;
            Properties.Settings.Default.FormatWithoutConfirmation = true;
            InitializeComponent();
            Properties.Settings.Default.FormatWithoutConfirmation = b;

我首先得出结论(在相关问题 here 的一些帮助下 - 询问如何使其工作),控件需要最初可见才能绑定工作,并且控件不可见会将控件放入为了看到可见的变化,永远不可见的捕获 22..

这似乎是一次性设置的事情,而不是“如果一个控件变得不可见,它就会停止侦听”的事情,因为如果它总是影响一个不可见的控件,那么一个开始可见的控件将变得不可见并且永远不会返回 -情况并非如此,最初可见的控件可以完美地打开和关闭可见性。

对我来说,最初可见理论的一个症结在于,根据 windows 设计器中的代码,绑定发生在 可见性设置之前:

        this.label4.AutoSize = true;
        this.label4.DataBindings.Add(new System.Windows.Forms.Binding("Enabled", global::Namespace.Properties.Settings.Default, "BooleanSetting", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
        this.label4.Enabled = global::Namespace.Properties.Settings.Default.BooleanSetting;
        this.label4.Location = new System.Drawing.Point(100, 100);
        this.label4.Name = "label4";
        this.label4.Size = new System.Drawing.Size(35, 13);
        this.label4.TabIndex = 11;
        this.label4.Text = "label4";
        this.label4.Visible = false;

在此处设置绑定时,可见性必须为 True,因为这是 Visible 属性的默认值。似乎稍后会发生其他事情以完成设置,或者在控件生命的早期(但不是这么早)有一个关键时刻发生在它身上的事情决定了它是否会听绑定属性更改


我觉得答案可能在 MSDN 的某个地方,作为我链接到的那个问题的答案之一说...

假设绑定到控件的 Visible 属性已损坏,尽管它有时会起作用。见http://support.microsoft.com/kb/327305,上面说了很多

...但是提供给 MSDN 的链接已失效。我读到的另一个相关问题提到,最初不可见的控件在创建时没有句柄,并将其作为可能的因素提出讨论


*不确定控件的生命何时开始,请参阅“创建绑定后设置可见性”注释

【问题讨论】:

  • 很有可能,除非控件具有实时 Handle 绑定,否则将无法正常工作。
  • 如果控件可见性的初始状态是false,则不会创建句柄。这会对属性绑定产生影响。你可以在这里看到它:CreateControl()。那里的注释已经解释过了。另请注意,该方法将其重载称为CreateControl(false),其中false 表示不要忽略可见状态。在那里您可以找到一条注释:只有在控件可见时才“创建”控件。如果您覆盖自定义控件的OnHandleCreated,您会看到它从未被调用过。

标签: winforms data-binding


【解决方案1】:

正如建议的那样,只要 Windows 窗体控件没有有效的 Windows 句柄,DataBinding 就不会处于活动状态。

多年前,当我不得不在一个带有选项卡控件的窗口上工作时,我第一次意识到这一点。我花了一段时间才明白为什么最初不可见的选项卡上的控件无法正确绑定,但在第一个选项卡上,一切都很好。

当我明白问题出在哪里后,我想找到一种解决问题的好方法,但当时项目负责人没有预算。所以,我走上了懒惰的道路,简单地循环了所有选项卡,让它们有机会非常短暂地可见,然后这些选项卡上的所有控件都有可能获得有效的句柄。

它真的很糟糕,因为在此过程中可以看到标签页闪烁。这最终从未得到修复,应用程序按原样发布。不用说,其他程序员和我自己都不太高兴,但客户从来没有抱怨过。去图吧。

因此,控件必须可见才能获取其句柄,然后才能隐藏。

祝你好运。

【讨论】:

  • 你对我提到的症结有什么意见吗?在 Designer.cs 中创建绑定的那一刻,控件 is visible=true.. 当控件可见为 false 时,是否会发生一些事情?例如“是的,绑定是像 LINQ 一样的延迟执行;它只发生在 .... 几秒钟后,当控件......并且在那一刻它是不可见的”..
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-14
  • 2011-10-04
  • 2015-10-26
  • 1970-01-01
  • 2014-07-10
  • 1970-01-01
相关资源
最近更新 更多