是否有适用于启用和可见属性的Windows窗体的通用接口?

时间:2014-10-31 11:46:45

标签: c# winforms

我想创建课程UserAction。该类接受一组小部件和一个回调。主要思想是有一个共同的对象,你可以在其中启用或禁用各种小部件(或可见/不可见)。

例如,对于 saveAction ,类UserAction的对象,您要添加 opSave ToolStripMenuItem)和< em> tbbSave (a ToolStripButton)。

this.saveAction = new UserAction( this.OnSave );
this.saveAction.AddControl( this.opSave );
this.loadAction.AddControl( this.tbbSave );

当您将saveAction已启用属性设置为false ...

saveAction.Enabled = false;

saveAction应该在集合的所有控件上运行,并将所有Enabled属性设置为 false

问题是Control,最初似乎是最常见的根类,包括已启用可见,但遗憾的是它不是根ToolStrip-whatever类的类。公共类是Component。它不包括那些属性。

我写的(丑陋的)代码是:

class UserAction {
    // ...
    public void SetControlsEnabled(bool value)
    {
            foreach(Component cmp in this.controls) {
                var c = cmp as Control;
                var tsi = cmp as ToolStripItem;

                if ( c != null ) {
                    c.Enabled = value;
                }
                else
                if ( tsi != null ) {
                    tsi.Enabled = value;
                }
           }

           return;
    }

    public bool Enabled {
        // ...
        set {
            this.SetControlsEnabled( value );
        }
    }

    // ...
    private List<Component> components;
}

用于访问 Enabled 属性的代码对于两种情况都是相同的,但遗憾的是没有定义属性 Enabled 的公共类或接口可见。或者,至少,我一直无法找到它。

上面的代码解决了ToolStrip-whatever组件和按钮等问题...遗憾的是,旧样式菜单和工具栏按钮未被覆盖,我必须检查MenuToolBarButton具体(同样,共同的祖先是Component,但该类没有定义这些属性。)

是否有更清洁和通用的解决方案?

2 个答案:

答案 0 :(得分:1)

只需添加一个抽象级别。这将消除丑陋的代码并真正使它变得更好。

class UserAction
{
    public void SetControlsEnabled(bool value)
    {
        foreach (ISupportEnabled component in this.components)
        {
            component.Enabled = value;
        }
    }

    public bool Enabled
    {
        // ...
        set
        {
            this.SetControlsEnabled(value);
        }
    }

    private List<ISupportEnabled> components = new List<ISupportEnabled>();

    public void AddComponent(ISupportEnabled component)
    {
        if (!components.Contains(component))
        {
            components.Add(component);
        }
    }
}

public interface ISupportEnabled
{
    bool Enabled { get; set; }
}

private class ControlAdapter : ISupportEnabled
{
    private readonly Control control;

    public ControlAdapter(Control control)
    {
        this.control = control;
    }

    public bool Enabled
    {
        get { return control.Enabled; }
        set { control.Enabled = value; }
    }
}

private class ToolStripItemAdapter : ISupportEnabled
{
    private readonly ToolStripItem toolStripItem;
    public ToolStripItemAdapter(ToolStripItem toolStripItem)
    {
        this.toolStripItem = toolStripItem;
    }

    public bool Enabled
    {
        get { return toolStripItem.Enabled; }
        set { toolStripItem.Enabled = value; }
    }
}

然后将其用作

UserAction userAction = new UserAction();
userAction.AddComponent(new ControlAdapter(this.MyTextBox));
userAction.AddComponent(new ToolStripItemAdapter(this.MyToolStripItem));

否则代码中的位置:

userAction.Enabled = false;

我希望你有这个想法,如果需要以这种方式使用更多的类,你需要为它创建一个新的适配器。如果您希望隐藏适配器创建代码,可以创建一个工厂来检查对象的类型并为其返回适配器。

答案 1 :(得分:1)

正如已经建议的那样:

foreach(dynamic cmp in this.controls)
{
    cmp.Enabled = value;
}