【问题标题】:C# WinForms Control on order changed event订单更改事件上的 C# WinForms 控件
【发布时间】:2017-03-26 12:37:18
【问题描述】:

我有一个带有自定义“选项卡”概念的 WinForms 应用程序,其中有 3 个按钮调用各自的面板“BringToFront()”方法。

由于这些面板都是在初始化表单时初始化的,但包含它们自己的单独功能,所以我不想在面板被“切换”到之前初始化一些更密集的任务。

例如,我的一个面板具有 Twitter 连接功能。如果我在面板初始化时初始化 Twitter 连接,它可能会失败,而理论上用户在完全不同的面板/功能上。

我只希望它在用户来到此面板后尝试连接到 Twitter。

所以,我一直在阅读 MSDN,但找不到在控件显示顺序更改时触发的事件。

我遇到过这些事件,但不确定哪些/如果有的话,这些是最有效的还是最好的:

Panel.OnVisibleChanged Panel.OnEnter Panel.OnGotFocus

我仍在学习 C#,因此感谢任何帮助/cmets。

【问题讨论】:

  • 为每个面板保留一个标志,以显示面板是否已加载。创建一个切换到面板的方法。在方法中,检查面板是否仍然没有加载,然后加载并设置标志并将其置于最前面。
  • 这个问题是后台任务的一个很好的例子。一旦您感觉当前面板的属性已设置,您就可以开始在后台初始化其他面板。 Panel 的 tag 属性可用于保存一个布尔值(无论是否设置)。此外,您可以隐藏和显示面板而不是 BringToFront。这将触发 VisibleChanged 事件,并且一旦它们可见就很容易捕获和处理。
  • 作为另一个选项,您可以将面板的内容封装在UserControl 类中,然后在第一次单击按钮时,检查相关面板是否为空,然后创建所需用户控件的实例并将其添加到面板中。您可以将加载逻辑封装在用户控件的Loading事件中。
  • 您将不得不停止为此寻找活动,没有任何活动。用户永远不能自己做任何事情来改变控件的 Z 顺序,只有您的代码可以做到这一点。因此解决方案非常简单,只需声明您自己的事件并在调用 BringToFront() 的相同方法中引发它。使用 TabControl 而不是自己动手是另一个简单的解决方案。

标签: c# .net winforms


【解决方案1】:

我遇到了同样的问题,我通过让每个选项卡实现一个接口并在我尝试加载它时触发它来修复它(我希望这是有道理的)(https://github.com/WithoutCaps/LimitlessUI/blob/master/LimitlessUI/TabsAdapter_WOC.cs)

第 30/31 行

if(tab is Tab_WOC)
     ((Tab_WOC)tab).onShowTab();

请随意使用此代码/库

注意:也有演示应用程序!

【讨论】:

  • 谢谢——虽然我觉得其他人可能会提供一种更强大的“正确”方式来做到这一点,这就是我实现它的方式:)
  • 对不起,我没有使用库,只是使用附加到所有面板类的接口的方法,这些面板类有一个方法,点击时由单个方法调用。
  • 我不确定其他遮阳篷是“合适的”还是“过于复杂”的,我只知道我的方法简单而干净。不要担心不使用我的库,这没什么大不了的,毕竟我主要是为自己写的:)
【解决方案2】:

这个问题是后台任务的一个很好的例子。一旦您感觉当前面板的属性已设置,您就可以开始在后台初始化其他面板。 Panel 的 tag 属性可用于保存一个布尔值(无论是否设置)。此外,您可以隐藏和显示面板而不是 BringToFront。这将触发 VisibleChanged 事件,并且在它们可见后易于捕获和处理。 这是为了向您展示后台工作人员代码的情况。

private void BackgroundWorker1_DoWork(object sender, System.ComponentModel.DoWorkEventArgs e)
    {
        if (!Convert.ToBoolean(Panel1.Tag)) {
            //Intialize panel1
            Panel1.Tag = true;
        }
        if (!Convert.ToBoolean(Panel2.Tag)) {
            //Intialize panel2
            Panel2.Tag = true;
        }
        if (!Convert.ToBoolean(Panel3.Tag)) {
            //Intialize panel3
            Panel3.Tag = true;
        }
    }

【讨论】:

    【解决方案3】:

    显然我不知道您的项目是如何布局的,但我看到了两个选项。

    选项 1:延迟加载的属性

    创建一个属性,当您调用它时会检查一个字段是否为空,如果是,则通过调用您想要的任何昂贵的类构造函数来初始化它。

    public TwitterCommunicator TwitterCommunicator => _twitterCommunicator ?? (_twitterCommunicator = new TwitterCommunicator());
    
    public void AnotherTwitterPanelMethod()
    {
        TwitterCommunicator.LoadTweets();
    }
    

    选项 2:使用Lazy<T>

    类似于延迟加载属性。实际使用 Lazy,它在您真正希望初始化对象时提供对象的延迟初始化。

    public partial class MainForm : Form
    {
        public MainForm()
        {
            Lazy<TwitterCommunicator> _lazyTwitter = new Lazy<TwitterCommunicator>();
        }
    }
    
    public void SomeTwitterPanelMethod()
    {
        _lazyTwitter.Value.LoadTweets();
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-03
      • 1970-01-01
      • 2013-10-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-10
      • 1970-01-01
      相关资源
      最近更新 更多