【问题标题】:How to create shortcut of a button on a panel at runtime?如何在运行时在面板上创建按钮的快捷方式?
【发布时间】:2018-07-10 13:16:58
【问题描述】:

我有一个包含很多按钮的面板(右侧面板)。我想在运行时动态地将选定按钮的快捷方式添加到另一个具有相同属性和事件的面板(左面板)。 按钮有很多属性,比如图像、文本、背景色、前景色……等等。

按钮也会在主面板中打开新表单:

private void butntest_Click(object sender, EventArgs e)
{
    this.main_panel.Controls.Clear();
    Form1 myForm = new Form1();
    myForm.TopLevel = false;
    myForm.AutoScroll = true;
    this.main_panel.Controls.Add(myForm);
    myForm.Show();
}

如何在左侧面板上创建快捷方式?

【问题讨论】:

  • 你看过这篇文章吗? stackoverflow.com/questions/25227969/…
  • 由于“快捷方式”是菜单和按钮中使用的术语,因此您的标题具有误导性。看起来您确实想要创建一个快捷方式,但想要一种简单的方法来创建副本,也就是克隆..?
  • 如果你真的发现所有这些属性都太多无法复制,你应该考虑制作一个可以重复使用的按钮类;把它挂在同一个事件上,你就完成了。或者写一个 buttonClone 工厂函数。
  • 控制克隆1 = CloneControl(button8);这将导致此错误:错误 CS0103 The name 'CloneControl' does not exist in the current or Button leftpannelbutton = new Button(); leftpannelbutton = button1.Clone();这将导致此错误:错误 CS1061“按钮”不包含“克隆”的定义,并且找不到接受“按钮”类型的第一个参数的扩展方法“克隆”(您是否缺少 using 指令或程序集引用?)
  • 没有内置的Clone 控制方法。您需要自己实现一个。

标签: c# .net winforms events panel


【解决方案1】:

您可以创建一个克隆方法,该方法接受一个按钮作为输入,并根据输入按钮的属性创建另一个按钮,还可以处理克隆按钮的点击事件,只需调用输入按钮的PerformClick 方法:

public Button Clone(Button input)
{
    var output = new Button();
    output.Text = input.Text;
    // do the same for other properties that you need to clone
    output.Click += (s,e)=>input.PerformClick();
    return output;
}

那么你可以这样使用它:

var btn = Clone(button1);
panel1.Controls.Add(btn);

另外,最好使用FlowLayoutPanelTableLayoutPanel,而不是面板,这样您就不需要自己处理位置和布局。

注意:如果它是一个动态 UI 并且用户可以重新排序命令按钮或创建任何你称之为快捷方式的东西,那么下一步你可能需要存储面板的状态以便能够应用程序关闭后下次加载应用程序时重新加载按钮。在这种情况下,最好考虑像命令模式这样的模式。然后你可以将你的命令作为类。然后你可以说哪个按钮在运行时负责运行哪个命令,你可以简单地使用它们的名称存储按钮和命令之间的关系。

【讨论】:

  • 我使用 flowlayoutpanel。按钮。如何存储状态?
  • 范围很广。正如我所说的那样,假设您有一些名为“Save”、“Load”、“New”、“Print”的命令。然后存储一些关于这些命令和按钮之间关系的信息就足够了。例如,您可以说“button1”运行“Save”,“button2”运行“Print”,等等。当您可以使用字符串描述某些内容时,这意味着您可以将此类信息存储在文件的数据库中。并再次加载并使用它。使用其名称查找控件很容易。使用名称运行方法也很容易。
  • 我现在有个小问题。我不想在左侧面板中多次添加按钮。我该怎么办?我在按钮克隆方法中尝试过,但这不起作用:foreach(flowLayoutPanel1.Controls 中的按钮 b){ if (!b.Text.ToLower().Contains(input.Text.ToLower())) { } }
  • 克隆方法不负责。您有很多选项可以停止创建重复的快捷方式。例如,您可以有一个List<string> 并将您要克隆的按钮的Name 属性添加到列表中。然后总是在克隆之前,检查列表是否包含按钮名称,这意味着你已经克隆了它。作为另一种解决方案,您可以在要克隆的按钮的Tag 属性中设置一些内容。这样,您可以防止克隆他们标记的按钮已经具有价值。
  • 我有一个新问题。当我在 flowlayoutpanel 中拖放控件时:MSDN Social 克隆按钮事件,将不再起作用。
【解决方案2】:

像这样创建类按钮

按钮 leftpannelbutton = new Button(); leftpannelbutton = button1.Clone();

现在 leftpannelbutton 等于 button1。现在只需将其添加到您的表单中。

查找下方(反射)

public static class ControlExtensions
{
    public static T Clone<T>(this T controlToClone) 
        where T : Control
    {
        PropertyInfo[] controlProperties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

        T instance = Activator.CreateInstance<T>();

        foreach (PropertyInfo propInfo in controlProperties)
        {
            if (propInfo.CanWrite)
            {
                if(propInfo.Name != "WindowTarget")
                    propInfo.SetValue(instance, propInfo.GetValue(controlToClone, null), null);
            }
        }

        return instance;
    }
}

【讨论】:

  • .Clone() 方法从何而来?我从未在 Windows 控件上见过它。
  • 编译器也没有。
  • 控制克隆1 = CloneControl(button8);这将导致此错误:错误 CS0103 The name 'CloneControl' does not exist in the current or Button leftpannelbutton = new Button(); leftpannelbutton = button1.Clone();这将导致此错误:错误 CS1061“按钮”不包含“克隆”的定义,并且找不到接受“按钮”类型的第一个参数的扩展方法“克隆”(您是否缺少 using 指令或程序集引用?)
  • 请参阅编辑后的帖子以获得解释。希望这会有所帮助
猜你喜欢
  • 2011-06-21
  • 2012-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多