是否可以让两个 Web 用户控件 (.ascx) 共享同一个代码隐藏类

本文关键字:控件 用户 ascx 共享 代码隐藏类 同一个 Web 两个 是否 | 更新日期: 2023-09-27 18:36:20

我遇到一种情况,我需要为 Web 用户控件提供两种完全不同的布局,但控件的代码隐藏保持相同非常重要。

有什么方法可以对两个不同的 Web 用户控件使用相同的代码隐藏吗?我尝试更改 Page 指令以使用相同的类,但偶尔在构建时,会生成一个包含重复控件的.designer.cs文件,因此会出现编译错误。

我还尝试从公共基类继承,但您无法看到此类中的任何控件,这使得采用此方法非常困难。

或者有没有办法防止设计器.cs类为"克隆"控件重新生成?

是否可以让两个 Web 用户控件 (.ascx) 共享同一个代码隐藏类

创建基类,并在其中实现通用逻辑。然后从此基类继承控件。对于从基类级别访问控件,请在基类级别为所需的每个控件抽象获取属性。在子控件类中实现这些属性。

public abstract class BaseControl : UserControl
{
  public abstract TextBox FirstName { get; }
  public void SomeLogicExample() 
  {
    FirstName.Text = "Something"; 
  }
}
public class ControlA : BaseControl
{
  public override TextBox FirstName
  {
    // txtFirstNameA is ID of TextBox, so it is defined in ControlA.designer.cs
    get { return txtFirstNameA; }
  }
}
public class ControlB : BaseControl
{
  public override TextBox FirstName
  {
    // txtFirstNameB is ID of TextBox, so it is defined in ControlB.designer.cs
    get { return txtFirstNameB; }
  }
}

或者,在运行时定位控件就不那么优雅了;因为您需要为搜索整个控件树付费,并且必须处理未找到控件的情况:

public abstract class BaseControl : UserControl
{
  public T GetControlByType<T>(Func<T, bool> predicate = null) where T : Control
  {
    var stack = new Stack<Control>(new Control[] { this });
    while (stack.Count > 0)
    {
      var control = stack.Pop();
      T match = control as T;
      if (match != null)
      {
        if (predicate == null || predicate(match))
        {
          return match;
        }
      }
      foreach (Control childControl in control.Controls)
      {
        stack.Push(childControl);
      }
    }
    return default(T);
  }    
  public TextBox FirstName
  {
    get { return GetControlByType<TextBox>(t => t.ID == "txtFirstName"); }
  }
  public void SomeLogicExample() 
  {
    FirstName.Text = "Something"; 
  }
}

我刚刚在VS 2012中对此进行了测试。

  1. 我添加了 2 个用户控件
  2. 从第二个控件中删除.ascx.cs.ascx.Designer.cs文件
  3. 修改了CodeBehindInherits属性的第二个控件的Page指令。无需为第二个控件生成设计器文件。

它有效。我不知道这是有效的方法与否。我已经通过在每个控件中添加一个Label并在代码隐藏中设置其值来对其进行测试。该值反映在两个控件中。

当一个用户控件中有一个 asp.net 控件而另一个用户控件中不存在该控件时,您可能会遇到问题。

除了@Ondrej Svejdar的正确答案之外,我建议您查看MVP设计模式,并可能将其与Web Forms代码一起使用。它有效,我在一个大项目中尝试过,结果并不比 MVC 项目中的关注点分离差。有一些框架可以帮助您实现它,但由于某种原因,我更喜欢自己实现它(毕竟它是几个基类和一个基接口)