【问题标题】:Triggering Button.PerformClick() on a hidden button在隐藏按钮上触发 Button.PerformClick()
【发布时间】:2014-08-07 06:57:09
【问题描述】:

我正在开发一个 C# WinForms 应用程序,其中有许多进程都由“主”应用程序管理。 在这个主应用程序中,每个进程都由其自己的FlowLayoutPanel 可视化,其中包含许多用于各种功能的按钮。我将这些面板称为“流程块”。

但是,当制作了许多这些过程时,并不是所有的块都可以轻松地显示在屏幕上。出于这个原因,我正在实施一个“紧凑模式”,它隐藏了所有进程块的所有按钮,只留下它们的名称、它们的状态和启动/停止按钮可见。然后我为每个进程块分配一个ContextMenuStrip,在其中我显示所有列为ToolStripMenuItem 的按钮,这样我就可以通过这种方式访问​​进程块的所有功能。我正在动态清除这些ContextMenuStrips 并在打开菜单时添加项目。 我通过遍历FlowLayoutPanel 的所有子控件来做到这一点,看看它们是否属于Button 类型,如果是,我将它们添加到ContextMenuStrip。见下面的代码sn-p:

private void PanelCmsOpened(object sender, EventArgs e) {
  try {
    ContextMenuStrip cMenuStrip = (ContextMenuStrip) sender;
    // Clear all items from the context menu
    cMenuStrip.Items.Clear();
    // Loop over all controls in the FlowLayoutPanel
    foreach (var c in CPanel.Controls) {
      Button btn = c as Button;
      if (btn == null) continue; // Not a button, continue
      // Get the text from the button
      string lbl = btn.Text;
      if (string.IsNullOrEmpty(lbl)) {
        try {
          // The button has no text (only an icon), so we get the tooltip text of the button
          lbl = PanelTooltip.GetToolTip(btn);
        }
        catch {
          // We can't get any text to display, so skip this button
          continue;
        }
      }
      // Add a new item to the ContextMenuStrip
      cMenuStrip.Items.Add(new ToolStripMenuItem(lbl,
                                                 btn.BackgroundImage,
                                                 (s, ea) => btn.PerformClick() // Perform a click on the button
                                                )
                                                {
                                                  Enabled = btn.Enabled
                                                });
    }
  }
  catch (Exception Ex) {
    MessageBox.Show("Fout bij openen van context menu: " + Ex.Message, "Fout", MessageBoxButtons.OK, MessageBoxIcon.Error);
  }
}

问题: 现在一切正常,只要按钮可见。但是,当进入紧凑模式时,我通过设置它们的 Button.Visible 属性来隐藏按钮。在这种情况下,什么都不会发生。我尝试在PerformClick 周围放置一个try-catch 块,但没有抛出异常。只是什么都没有发生。有谁知道如何使隐藏按钮工作?

【问题讨论】:

    标签: c# winforms button contextmenu


    【解决方案1】:

    PerformClick 在执行点击之前检查按钮是否可供点击。隐藏的按钮被视为不可用。您可以在执行单击之前简单地显示按钮,并在单击后将其隐藏:

     cMenuStrip.Items.Add(
         new ToolStripMenuItem(lbl, btn.BackgroundImage, (s, ea) => {
              var size = btn.Size;
              btn.Size = Size.Empty; // button still will be invisible
              btn.Show(); // make it clickable
              btn.PerformClick();
              btn.Hide();  // hide again
              btn.Size = size; // restore original size
            });
    

    注意:如果你还需要添加一些可见的按钮,那么你应该单独处理它们以避免闪烁

     cMenuStrip.Items.Add(new ToolStripMenuItem(
          lbl, btn.BackgroundImage, (s, ea) => ClickButton(btn)));
    

    ClickButton 是一个根据按钮是否可见执行不同逻辑的方法:

    private void ClickButton(Button button)
    {
        if (button.Visible)
        {
            button.PerformClick();
            return;
        }
    
        var size = button.Size;
        button.Size = Size.Empty;
        button.Show();
        button.PerformClick();
        button.Hide();
        button.Size = size;
    }
    

    【讨论】:

    • 感谢 Sergey,这正是我使用 Atanas 帮助解决的方法。感谢您为我们写出来!
    【解决方案2】:

    你唯一不能做的就是设置visible = false;

    除此之外,你可以使用任何技巧来隐藏按钮:你可以将它们堆叠在另一个控件后面,你可以将它们从任何方向移出视线,甚至将它们移动到不同的父级中:

    隐藏它们:

    panel1.Size = Size.Empty;
    button1.Parent = panel1;
    //..
    

    再次显示它们:

    button1.Parent = this;
    //..
    

    假设他们坐在表格上。

    请注意,它们将保持原来的位置和大小;注意 tab-order 和 z-order 的变化!

    【讨论】:

    • 感谢您的建议。因为我使用 FlowLayoutPanel,所以这些方法不太适用于我的情况,因为 Panel 负责定位和填充等。但是,此解决方案可能对其他人有用!
    • 啊,对不起,我忽略了。
    【解决方案3】:

    如果按钮不可见,则不会引发 Click 事件。 一种选择是采用按钮单击事件中的代码并将其添加为单独的方法。然后调用该方法而不是 PerformClick 行。但是,如果您在每次单击按钮时都执行相同的操作,这将起作用。

    使按钮透明的另一个选项。这将使它们对客户端不可见,并且 PerformClick 事件将正常工作。您可以在以下链接中看到:Drawing a transparent button

    希望这会有所帮助。

    【讨论】:

    • 感谢您的回答阿塔纳斯。问题是我正在迭代按钮,因此,我不知道 Click 功能背后的代码是什么。恐怕让按钮透明对我没有任何好处,因为它不会释放任何空间(按钮仍然存在)。您给了我一个新想法:我将尝试将按钮的宽度设为 0。
    • 另一种方法是让它们可见。创建一个将在 PerformClick 行上并接受按钮作为参数的方法。然后在方法内的按钮上执行 PerformClick,然后隐藏按钮。
    • 这行得通。但是,某些按钮会创建一个对话框,这意味着该按钮在对话框关闭之前一直可见。也许我可以结合使它们可见并暂时将它们的宽度设置为 0 的方法。
    • 是的,这行得通!将可见性临时设置为 true 并将宽度设置为 0,我看到的唯一故障是添加到面板的一点填充。对我来说已经足够好了! Atanas,如果您可以发布您的方法作为答案,我可以正式接受它;-)
    • 我以与 Sergeys 回答类似的方式解决了它。感谢您的帮助阿塔纳斯!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-22
    • 1970-01-01
    • 2015-09-26
    相关资源
    最近更新 更多