所以我得到了以下课程......
public partial class CommandBar : UserControl { .. }
...我包含在.ascx文件中,如此...
<%@ Register Src="~/.../CommandBar.ascx" TagName="CommandBar" TagPrefix="uc1" %>
...
<uc1:CommandBar ID="CommandBarTop" runat="server" ... />
我目前的目标是创建一个通用方法,允许用户将所有控件设置为只读递归。该方法应提供可选参数,以指定要忽略的List<Type>
个控件。在此列表中,我想通过typeof(CommandBar)
传递此CommandBar来忽略这些。
一切都像预期的那样有效但我在找出匹配这些类型的正确方法时遇到了一些麻烦。
考虑以下事项;
Object o; // control to check, in this case the `CommandBarTop` object
Type t; // type to ignore
我希望它像这样容易:
if (o is t){
// ignore
}
...但我得到语法异常“预期值为常量值”。所以我尝试了以下设置:
if (t == typeof(o)){
// ignore
}
它确实编译但是没有像预期的那样工作。问题似乎是类型不匹配。看一下调试器,我得到以下结果:
t => {Name = "CommandBar" FullName = "My.Name.Space.Controls.CommandBar"} System.Type {System.RuntimeType}
o => {ASP.controls_commandbar_ascx} object {ASP.controls_commandbar_ascx}
o.base
实际上是t
类型,但首先它不可访问,其次该方法应该是通用的,检查匹配的基类型可能并不总是按照我想要的方式执行。
我假设ASP.NET在运行时生成一个控件包装器,然后发送给用户。这个假设基于我在调试器中看到的汇编代码库。它说:
t.Assembly.CodeBase => "file:///.../bin/My.Name.Space.Project.DLL" string
o.GetType().Assembly.CodeBase => "file:///C:/Windows/Microsoft.NET/Framework/.../Temporary ASP.NET Files/root/.../App_Web_....DLL" string
我也尝试过匹配类型GUID,但因为它们基本上不是同一类型也不起作用。
编辑1
我认为如果我向您展示我的方法将控件设置为只读递归
可能会有所帮助public static void SetControlRecursivelyReadOnly(Object control, Boolean readOnly, IEnumerable<Type> controlTypesToIgnore = null)
{
if (null == control)
{
return;
}
new List<KeyValuePair<Type, String>>
{
// define all types which are relevant to access possible child controls
new KeyValuePair<Type, String>(typeof(ControlCollection), "Controls"),
new KeyValuePair<Type, String>(typeof(TableRow), "Rows"),
new KeyValuePair<Type, String>(typeof(TableCell), "Cells")
}.ForEach(x =>
{
// get defined property
Object property = typeof(Reflection).GetMethod("GetProperty")
.MakeGenericMethod(x.Key)
.Invoke(null,
new[]
{
control,
x.Value
});
// check if property is found and is IENumerable
if (!(property is IEnumerable))
{
return; // continues the foreach loop
}
// call recursive
foreach (Object o in (IEnumerable) property)
{
// <--- TODO CHECK IF CONTROL TYPE SHOULD BE IGNORED --->
SetControlRecursivelyReadOnly(o, readOnly);
}
});
// set relevant properties accordingly to readOnly parameter
new List<Tuple<PropertyInfo, Boolean>>
{
new Tuple<PropertyInfo, Boolean>(control.GetType().GetProperty("ReadOnly"), readOnly),
new Tuple<PropertyInfo, Boolean>(control.GetType().GetProperty("EnableButtons"), !readOnly),
new Tuple<PropertyInfo, Boolean>(control.GetType().GetProperty("Enabled"), !readOnly)
}.Where(x => null != x.Item1)
.ToList()
.ForEach(x => x.Item1.SetValue(control, x.Item2, null));
}
现在提出我的问题;有谁知道如何解决这个问题?
提前致谢!
答案 0 :(得分:0)
您需要递归循环页面中的所有控件。
public void FindChildControlsRecursive(Control control)
{
foreach (Control childControl in control.Controls)
{
// add .BaseType in the next line if it's a UserControl
if (childControl.GetType() == typeof(T))
{
_foundControls.Add((T)childControl);
}
else
{
FindChildControlsRecursive(childControl);
}
}
}
private readonly List<T> _foundControls = new List<T>();
public IEnumerable<T> FoundControls
{
get { return _foundControls; }
}
以同样的方式,您可以设置包含要排除的控件的属性。
答案 1 :(得分:0)
尝试使用您的类型名称prop。像下面的东西应该工作
{{1}}