【问题标题】:Does data binding work on invisible control?数据绑定是否适用于隐形控件?
【发布时间】:2022-02-05 17:49:02
【问题描述】:

这是 winforms 的 .net 问题,而不是 asp.net。

我有一个带有多个选项卡的 Windows 窗体。我在加载表单时设置了所有控件的数据绑定。但我注意到第二个选项卡上控件的数据绑定不起作用。这些绑定仅在加载表单并选择第二个选项卡时才起作用。这让我产生了怀疑:数据绑定只有在绑定控件变得可见时才起作用。

谁能告诉我这是真的还是假的?测试这个并不难,但我想知道一些确认。

谢谢

【问题讨论】:

    标签: c# .net winforms


    【解决方案1】:

    你是对的。在控件可见之前,不会更新数据绑定控件。

    目前我能找到的唯一参考是this MSDN thread

    【讨论】:

    • 哇。我想我总是通过数据源获取数据 - 我真的不知道绑定只有在控件可见时才真正起作用。
    • 我个人认为这是一个功能。
    【解决方案2】:

    您的问题与 TabControl 的行为有关。见Microsoft bug report。我针对该问题发布了一个解决方法,该问题将 TabControl 子类化并在创建控件或创建句柄时“初始化”所有选项卡页。以下是解决方法的代码。

    public partial class TabControl : System.Windows.Forms.TabControl
    {
        protected override void OnHandleCreated(EventArgs e_)
        {
            base.OnHandleCreated(e_);
            foreach (System.Windows.Forms.TabPage tabPage in TabPages)
            {
                InitializeTabPage(tabPage, true, Created);
            }
        }
    
        protected override void OnControlAdded(ControlEventArgs e_)
        {
            base.OnControlAdded(e_);
            System.Windows.Forms.TabPage page = e_.Control as System.Windows.Forms.TabPage;
            if ((page != null) && (page.Parent == this) && (IsHandleCreated || Created))
            {
                InitializeTabPage(page, IsHandleCreated, Created);
            }
        }
    
        protected override void OnCreateControl()
        {
            base.OnCreateControl();
            foreach (System.Windows.Forms.TabPage tabPage in TabPages)
            {
                InitializeTabPage(tabPage, IsHandleCreated, true);
            }
        }
    
        //PRB: Exception thrown during Windows Forms data binding if bound control is on a tab page with uncreated handle
        //FIX: Make sure all tab pages are created when the tabcontrol is created.
        //https://connect.microsoft.com/VisualStudio/feedback/details/351177
        private void InitializeTabPage(System.Windows.Forms.TabPage page_, bool createHandle_, bool createControl_)
        {
            if (!createControl_ && !createHandle_)
            {
                return;
            }
            if (createHandle_ && !page_.IsHandleCreated)
            {
                IntPtr handle = page_.Handle;
            }
            if (!page_.Created && createControl_)
            {
                return;
            }
            bool visible = page_.Visible;
            if (!visible)
            {
                page_.Visible = true;
            }
            page_.CreateControl();
            if (!visible)
            {
                page_.Visible = false;
            }
        }
    } 
    

    【讨论】:

    • 考虑到没有使用该值,“IntPtr handle = page_.Handle”到底在做什么?
    • 强制创建句柄
    • 谢谢。我想是这样的。顺便说一句,我试过了,但它对我不起作用。当 IsHandleCreated 和 Created 仍然为假时,我的控件被添加了。我想一些调整会涵盖这种情况,但我采取了不同的路线:在完成所有绑定之后,我找到所有绑定控件并将 VisibleChanged 处理程序添加到不可见的控件,当它们变得可见时它将执行我需要的操作。跨度>
    【解决方案3】:

    我们遇到了类似的问题。我们正在尝试写入 2 个绑定的、不可见的字段,以便我们可以更改写入数据集的格式。这在对象可见时工作正常,但在可见属性更改为 false 时停止工作。

    为了解决这个问题,我添加了以下代码:

                // Stop our screen flickering.
            chSplitContainer.Panel2.SuspendLayout();
            // Make the bound fields visible or the binding doesn't work.
            tbxValueCr.Visible = true;
            tbxValueDb.Visible = true;
    
            // Update the fields here.
            <DO STUFF>
    
            // Restore settings to how they were, so you don't know we're here.
            tbxValueCr.Visible = false;
            tbxValueDb.Visible = false;
            chSplitContainer.Panel2.ResumeLayout();
    

    【讨论】:

      【解决方案4】:

      我自己也为此苦苦挣扎,并得出结论,除了显然进行子类化(请参阅 hjb417 的答案)之外,唯一的解决方法是使另一个选项卡可见。切换到另一个选项卡并在表单可见之前立即返回上一个选项卡不起作用。如果您不想让第二个选项卡可见,我使用以下代码作为解决方法:

      this.tabControl.SelectedTab = this.tabPageB; 
      this.tabPageB.BindingContextChanged += (object sender, EventArgs e) => {
          this.tabContainerMain.SelectedTab = this.tabPageA; 
      };
      

      假设 tabPageA 是可见选项卡,而 tabPageB 是您要初始化的不可见选项卡。这将切换到 pageB,并在数据绑定完成后切换回来。这对表单中的用户是不可见的。

      仍然是一个丑陋的黑客,但至少这是可行的。当然,当你有多个标签时,他的代码会变得更加丑陋。

      【讨论】:

        【解决方案5】:

        这不是我直接遇到的。但是,您可能会遇到BindingContext 的问题。没有更多细节很难说,但如果我是你,我会设置一个断点并确保所有控件都绑定在同一个上下文中。

        【讨论】:

          【解决方案6】:

          根据答案,我制定了适合我的方法:

           public partial class Form1: Form
           {
              private void Form1_Load(object sender, EventArgs e)
              {
                  ...
                  forceBindTabs(tabControl1);
              }
          
              private void forceBindTabs(TabControl ctl)
              {
                  ctl.SuspendLayout();
          
                  foreach (TabPage tab in ctl.TabPages)
                      tab.Visible = true;
          
                  ctl.ResumeLayout();
              }
           }
          

          除了解决问题之外,选项卡在开始时加载,当用户点击它们时显示更快。

          【讨论】:

            【解决方案7】:

            很抱歉对这个线程进行了死灵处理,但是使用这种方法很容易强制不可见控件的数据绑定/句柄准备好:

            https://social.msdn.microsoft.com/Forums/vstudio/en-US/190296c5-c3b1-4d67-a4a7-ad3cdc55da06/problem-with-binding-and-tabcontrol?forum=winforms

            简单地说,假设您的控件位于标签页tpg_Second(或tabCtl.TabPages[1])中,在您对其数据进行任何操作之前,请先调用它:

            tpg_Second.Show()
            

            这不会激活任何标签页,但是 viola,控件的数据绑定现在应该可以工作了。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-04-18
              • 2011-05-18
              • 1970-01-01
              • 2019-09-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2018-01-03
              相关资源
              最近更新 更多