如何在不同的自定义控件之间共享行为?

问题描述 投票:1回答:3

我有两个自定义控件:CustomTextBoxCustomNumericUpDown。我希望他们有一个共享行为,它包含一些方法和一些属性。

我提出的解决方案:

  1. 两者都应该扩展包含共享行为的抽象类。问题是,一个扩展TextBox另一个扩展NumericUpDown。我想不出两种方法都可以继承我的抽象类,除了多重继承,这在C#中是不允许的。
  2. 实现共享接口。这显然是愚蠢的,因为接口不能有实现。
  3. 使用扩展方法。更具体地说,使它们共享一个接口,并为该接口创建扩展方法。问题是you cannot (currently) have extension properties in C#,我真的不想因为the principle of least astonishment而使用实际方法来实现getter和setter。

是否有一个优雅的方法来解决这个问题,不涉及重复代码?


编辑:


例如,我希望CustomTextBoxCustomNumericUpDown都有ValidateInput()方法和ValidationRules属性。即,我想为它们两者添加一个方法和一个属性。

c# winforms inheritance
3个回答
1
投票

远非优雅,但如果您不需要依赖派生控件的特定实现细节,您可以使用接口的组合(以强制执行您想要的属性和方法)和delegation(以封装) /集中共享行为)。

派生控件中接口的实现完全是样板文件,并始终在其他地方委托。

public class ValidationService
{
    public void RegisterRules(Control control, string[] rules)
    {
        // store rules
    }

    public string[] GetRules(Control control)
    {
        // retrieve rules
    }

    public void Validate(Control control)
    {
        // validate
    }
}

public interface IValidatable
{
    ValidationService ValidationService { get; set; }
    string[] Rules { get; set; }
    void ValidateControl();
}

public class MyTextBox : TextBox, IValidatable
{
    public ValidationService ValidationService { get; set; }

    public string[] Rules
    {
        get => ValidationService.GetRules(this);
        set => ValidationService.RegisterRules(this, value);
    }

    public void ValidateControl()
    {
        ValidationService.Validate(this);
    }
}

public class MyNumericUpDown : NumericUpDown, IValidatable
{
    public ValidationService ValidationService { get; set; }

    public string[] Rules
    {
        get => ValidationService.GetRules(this);
        set => ValidationService.RegisterRules(this, value);
    }

    public void ValidateControl()
    {
        ValidationService.Validate(this);
    }
}

但是,如果您的验证行为依赖于派生控件的特定详细信息,则此方法会变得混乱。


1
投票

这是我的想法,

创建具有两个控件的常用功能的类,

将它注入两个控件初始化,可以访问公共类的常用函数

public class CommonFunctions
{
    public void ValidateInput(Object sender){
        // do your validation logic
    }
}

public class CustomTextBox : TextBox 
{
    private CommonFunctions _commonFunctions;

    public CustomTextBox(CommonFunctions commonFunctions)
    {
            _commonFunctions = commonFunctions;
    }

    private void Control_TextChanged(Object sender,EventArgs e)
    {
              _commonFunctions.ValidateInput(sender);
    }

}

public class CustomNumericUpDown : NumericUpDown 
{
    private CommonFunctions _commonFunctions;

    public CustomNumericUpDown(CommonFunctions commonFunctions)
    {
            _commonFunctions = commonFunctions;
    }

    private void Control_TextChanged(Object sender,EventArgs e)
    {
              _commonFunctions.ValidateInput(sender);
    }
}

0
投票

创建一个包含通用功能的基类。为您需要的每个控件扩展该类,并将控件放在该类中。

public class MyUserControl : UserControl 
{
   public MyUserControl() : base() 
   {
   }
   // add common behaviour here (validation, etc)
}

public class MyTextBox : MyUserControl 
{
   public MyTextBox() : base() 
   {
      Add(new TextBox());
   }
   ...
}