【问题标题】:Generating windows forms controls dynamically动态生成窗体控件
【发布时间】:2016-09-27 19:47:37
【问题描述】:

我正在尝试使用抽象工厂模式创建一个具有可自定义“主题”的表单应用程序(只是为了获得一些经验)。我已经创建了一个这样的主题工厂的实现:

public class BlueTheme : IThemeFactory
{
    public Button CreateButton() => new BlueButton();
    // ... more controls here ...
}

现在我通过 Form 的构造函数传递一个 IThemeFactory 实例:

private IThemeFactory _themeFactory;

public Form1(IThemeFactory theme)
{
    _themeFactory = theme; // e.g. new BlueTheme()
    InitializeComponent();
}

我的问题是:有没有办法让我的表单使用IThemeFactory.CreateButton() 方法来生成表单上的所有按钮?

【问题讨论】:

  • 我正在考虑在初始化后用主题按钮替换(映射)所有普通按钮,但必须有更好的解决方案,对吧?

标签: c# winforms user-interface design-patterns factory-pattern


【解决方案1】:

尽管是由 Windows 窗体设计器创建的,InitializeComponent() 方法是完全正常的并且可以编辑。它位于文件中:*.Designer.cs(其中* 是您的班级名称)。

该方法包含组件的所有构造函数调用,但您可以继续将它们替换为工厂方法调用。请注意,这可能会阻止您使用 Windows 窗体设计器来编辑布局,但您可以在设计器中执行的所有操作都可以通过编辑 *.Designer.cs* 文件中的代码来完成。

【讨论】:

    【解决方案2】:

    由于似乎不可能使用工厂来实现我试图做的事情,我决定通过递归循环来设置现有组件的样式:

    public abstract class Theme
    {
        public delegate void ButtonStyler(Button button);
        public ButtonStyler StyleButton { get; }
    
        protected Theme(ButtonStyler styleButton)
        {
            StyleButton = styleButton;
        }
    
        // Apply this theme to all components recursively
        public void Style(Control parent)
        {
            if (parent is Button) StyleButton((Button) parent);
            foreach (Control child in parent.Controls) Style(child);
        }
    }
    
    public class BlueTheme : Theme
    {
        public BlueTheme() : base(
            button =>
            {
                button.BackColor = Color.DeepSkyBlue;
                button.ForeColor = Color.White;
                button.FlatStyle = FlatStyle.Flat;
            }) {}
    }
    

    在这个例子中我只实现了按钮,但是任何组件样式都可以很容易地添加,使用主题很简单:

    public Form1(Theme theme)
    {
        InitializeComponent();
        theme.Style(this);
    }
    
    private static void Main() {
        Application.Run(new Form1(new RedTheme()));
    }
    

    虽然这可行,但我仍然很好奇这是否可以通过工厂实现,就像在最初的问题中解释的那样。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-04
      • 1970-01-01
      • 2020-08-21
      • 2011-03-26
      • 1970-01-01
      相关资源
      最近更新 更多