【问题标题】:C# UserControl Visible Property Not ChangingC# UserControl 可见属性不变
【发布时间】:2012-06-25 01:05:24
【问题描述】:
Debug.WriteLine(ucFollow.Visible);
ucFollow.Visible = true;
Debug.WriteLine(ucFollow.Visible);

ucFollow 是一个自定义的 UserControl,没什么花哨的。上面的代码打印出来:

False
False

最糟糕的是,这确实切换了 UserControl 的实际可见性(即,一旦调用此代码,ucFollow 就会出现),但 Visible 属性似乎不知何故不是......好吧,在后端可见,并且不反映更改,即使 UI 本身也是如此。

我什至不知道从哪里开始解决这个问题。有没有人知道什么可能会导致这种疯狂?

编辑:这是 Visual Studio 2010 中的标准 C# WinForm。

【问题讨论】:

  • 好吧,如果你破坏了 C#,我担心你将不得不修复它。
  • 是否存在控制层次结构?如果控件包含在不可见的父级中,则将 visible 分配给 true 并不一定表明该控件可见。
  • 看到这种行为可能有很多原因,我不会直接跳到 c# 错误结论。请提供一个简单的可重现示例。
  • @TheDramaLlama 我们当然需要一个可重现的例子。我们没有你的代码库,只能猜测。
  • 运行此代码时表单是否可见(即此代码是否在 Form.Load 事件中运行?)。如果控件在物理上不可见,它将返回 false,直到它可见。

标签: c# winforms user-controls


【解决方案1】:

我没有破坏 C#! :)

原来罪魁祸首是 Form.Visible 属性。在 Form.Visible 设置为 true 之前,表单上的所有控件都将不可见(Visible = false)。

但是,您仍然可以设置可见属性 - 它们只是在 Form.Visible 属性设置为 true 之前不会生效。

换句话说,当我调用ucFollow.Visible = true 时,我的程序确实在注册它——然而,在代码中,ucFollow 的父 Form.Visible 仍然是错误的。因此,调试器和我的打印语句都识别出,“嘿,这个控件的父窗体仍然不可见,所以这个控件不可见。句号。”

一旦表单可见,所有更改都会生效,一切正常。

故事的寓意:不要依赖控件的可见性属性,除非包含它们的表单已经可见并正在运行。

【讨论】:

  • 如果您想了解控件是否可见(如果父控件可见),您可以查看我的问题here 以获得解决方案
  • 您可以将此标记为答案,这样做完全可以。控件可见性(在设计模式下)的另一个奇怪而奇妙的行为是,当您有一个未在 InitializeComponent() 中声明的 UserControl 时。(无论出于何种原因)...如果您打开表单,则未显示控件它也没有列在控件的“属性”下拉列表中。
【解决方案2】:

罪魁祸首是控件 Visible 属性实际上是一个属性 (with get; set;) 并且 set 将分配给内部 m_Visible 成员,但 get 将查看所有父控件,并且只有在所有父控件都具有 m_Visible 时才会返回 true == 真

【讨论】:

    【解决方案3】:

    这是假设属性和字段是同一事物的危险。当然,它们在概念上非常相似(这就是重点),但它们在机制上却明显不同。看看ucFollow.Visible = true 实际做了什么:

    protected virtual void SetVisibleCore(bool value)
    {
        try
        {
            HandleCollector.SuspendCollect();
            if (this.GetVisibleCore() != value)
            {
                if (!value)
                {
                    this.SelectNextIfFocused();
                }
                bool flag = false;
                if (this.GetTopLevel())
                {
                    if (this.IsHandleCreated || value)
                    {
                        SafeNativeMethods.ShowWindow(new HandleRef(this, this.Handle), value ? this.ShowParams : 0);
                    }
                }
                else
                {
                    if (this.IsHandleCreated || (value && this.parent != null && this.parent.Created))
                    {
                        this.SetState(2, value);
                        flag = true;
                        try
                        {
                            if (value)
                            {
                                this.CreateControl();
                            }
                            SafeNativeMethods.SetWindowPos(new HandleRef(this.window, this.Handle), NativeMethods.NullHandleRef, 0, 0, 0, 0, 23 | (value ? 64 : 128));
                        }
                        catch
                        {
                            this.SetState(2, !value);
                            throw;
                        }
                    }
                }
                if (this.GetVisibleCore() != value)
                {
                    this.SetState(2, value);
                    flag = true;
                }
                if (flag)
                {
                    using (new LayoutTransaction(this.parent, this, PropertyNames.Visible))
                    {
                        this.OnVisibleChanged(EventArgs.Empty);
                    }
                }
                this.UpdateRoot();
            }
            else
            {
                if (this.GetState(2) || value || !this.IsHandleCreated || SafeNativeMethods.IsWindowVisible(new HandleRef(this, this.Handle)))
                {
                    this.SetState(2, value);
                    if (this.IsHandleCreated)
                    {
                        SafeNativeMethods.SetWindowPos(new HandleRef(this.window, this.Handle), NativeMethods.NullHandleRef, 0, 0, 0, 0, 23 | (value ? 64 : 128));
                    }
                }
            }
        }
        finally
        {
            HandleCollector.ResumeCollect();
        }
    }
    

    (代码由 ILSpy 提供。)

    你的答案就在那个饱受折磨的逻辑迷宫中。

    【讨论】:

    • 我感觉我的解决方案可以与上述逻辑迷宫中的某些东西相关联,但现在是星期五,我懒得去找它。 :)
    猜你喜欢
    • 2011-01-18
    • 2012-05-23
    • 2019-08-17
    • 1970-01-01
    • 2014-12-02
    • 2010-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多