2015-01-06 45 views
2

我有一种情况,我需要为Web用户控件拥有两种完全不同的布局,但是对于控件的代码隐藏保持相同非常重要。我可以让两个Web用户控件(.ascx)共享相同的代码隐藏类吗?

有什么办法可以为两个不同的Web用户控件使用相同的代码隐藏?我试着改变Page指令来使用同一个类,但是偶尔当你编译时,.designer.cs文件会被重复控件生成,所以你会得到一个编译错误。

我也尝试从一个普通的基类继承,但是你不能看到这个类的任何控件,这使得很难采取这种方法。

或者有没有办法阻止为“克隆”控件重新生成designer.cs类?

+0

你在代码隐藏中有很多业务逻辑吗?如果是这样,可以将它放置在一个单独的类中,并由代码隐藏用于两个用户控件? –

+0

不是“业务逻辑”,而是验证控件和处理输入等。由于此代码严重访问控件,并且无法从基类中看到控件,所以我认为这不会很好解决问题的方法:( – NickG

+0

)您可以创建一个包含您的验证逻辑的静态类,而不是基类,这些方法将作为参数传递给您的控件。 –

回答

2

我刚才在VS测试这个2012年

  1. 我加入2用户控制
  2. 已删除.ascx.cs.ascx.Designer.cs来自第二控件的文件
  3. 已修改Page第二控件的指令为CodeBehindInherits属性。不需要为第二个控件生成Designer文件。

它的工作原理。我不知道这是否有效。 我已经通过在每个控件中添加一个Label并在代码后面设置它的值来测试它。价值反映在两个控件中。

如果在一个用户控件中有一个asp.net控件,而在其他控件中不存在,则可能会遇到问题。

+0

.designer.cs文件有时会重新填充(我无法弄清楚何时!)当我这样做时。 – NickG

+0

只有在尝试将其转换为Web应用程序选项时,'.designer.cs'才会重新生成。但是使用这种方法,您无法为上述控件生成'.designer.cs',并在转换时抛出错误。其他功能将按照应有的方式工作。尝试一下。 – Bharadwaj

+0

谢谢你是对的。关键似乎是删除文件而不是清空文件。这样.designer.cs不会被重新创建。 – NickG

2

创建基类,并在那里实现通用逻辑。然后从这个基类继承控件。为了从基类级别访问控件,抽象获取您需要的每个控件的基类级属性。在子控件类中实现这些属性。

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"; 
    } 
} 
+0

感谢您的回复,但我选择了我接受的答案,因为它更简单,只涉及按删除键;) – NickG

+0

@NickG我强烈建议重新考虑您的决定,您正在搞乱并改变默认的asp.net/VS行为可能会导致更长远的麻烦。 –

1

除了@Ondrej Svejdar的正确答案之外,我建议你看看MVP design pattern,并可能将它用于Web窗体代码。它的工作原理,我已经在一个大项目中尝试过了,结果并不比在MVC项目中分离关注点差。有框架可以帮助你实现它,但由于某种原因,我更喜欢自己实现它(毕竟它是几个基类和一个基本接口)

相关问题