C# 如何加载给定类型的用户控件
如果给定用户控件(.ascx)的类型(即C# 如何加载给定类型的用户控件,c#,asp.net,dynamic-usercontrols,C#,Asp.net,Dynamic Usercontrols,如果给定用户控件(.ascx)的类型(即typeof(MyUserControl)),是否有方法实例化和使用它 使用常规asp.net控件(如textbox或dropdownlist),您只需创建一个新实例并将其添加到控件集合中即可。这似乎不适用于用户控件。虽然您可以创建一个新实例并将其添加到集合中,并触发其所有事件,但它实际上不会呈现到页面中。通常,您会使用.ascx的路径调用Page.LoadControl() 如果您所拥有的只是它的类型,那么这就出现了一个问题。如何获取.ascx的路径以提
typeof(MyUserControl)
),是否有方法实例化和使用它
使用常规asp.net控件(如textbox或dropdownlist),您只需创建一个新实例并将其添加到控件集合中即可。这似乎不适用于用户控件。虽然您可以创建一个新实例并将其添加到集合中,并触发其所有事件,但它实际上不会呈现到页面中。通常,您会使用.ascx的路径调用Page.LoadControl()
如果您所拥有的只是它的类型,那么这就出现了一个问题。如何获取.ascx的路径以提供给
LoadControl
方法。理想情况下,我也希望不必引用页面对象您可能在这里运气不好
无法获得执行此操作的帮助
他们说这是不可能的。不。这是不可能的;必须提供ASCX虚拟路径以动态加载带有标记的用户控件,并且没有虚拟路径类型的内部映射 然而,因为我仍然很懒惰,所以我使用的方法仍然是“类型安全”的,并将解决问题隔离到代码中的单个位置。它仍然需要访问“页面对象”,但在其他方面需要处理愚蠢的细节 以下是简要说明:
//
///使用给定类型加载控件。
///
公共对象加载控件(类型t,第页)
{
尝试
{
//解析程序的定义在下一个代码位中
var partialPath=resolver.ResolvePartialPath(t);
var fullPath=ResolvePartialControlPath(partialPath);
//现在我们已经从虚拟路径加载了控件。很简单。
返回页面。LoadControl(完整路径);
}捕获(例外情况除外)
{
抛出新异常(“控件映射失败”,ex);
}
}
///
///按特定类型加载控件。
///(前一个方法的强类型包装器)。
///
公共T LoadControl(第页),其中T:Control
{
尝试
{
返回(T)负载控制(类型(T),第页);
}捕获(例外情况除外)
{
抛出新异常(string.Format)(
“未能为类型{0}加载控件”,
类型(T.名称),ex);
}
}
///
///给定部分控制路径,返回完整(相对于根)控制路径。
///
字符串解析PartialControl路径(字符串partialPath)
{
返回string.Format(“{0}{1}.ascx”,
ControlPathRoot,partialPath);
}
ControlResolver的代码列表:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FooBar
{
class ControlResolver
{
const string BaseNamespace = "TheBaseControlNameSpace";
readonly IDictionary<Type, string> resolvedPaths = new Dictionary<Type, string>();
/// <summary>
/// Maps types to partial paths for controls.
///
/// This is required for Types which are NOT automatically resolveable
/// by the simple reflection mapping.
/// </summary>
static readonly IDictionary<Type, string> MappedPartialPaths = new Dictionary<Type, string>
{
{ typeof(MyOddType), "Relative/ControlPath" }, // No virtual ~BASE, no .ASXC
};
/// <summary>
/// Given a type, return the partial path to the ASCX.
///
/// This path is the path UNDER the Control Template root
/// WITHOUT the ASCX extension.
///
/// This is required because there is no mapping maintained between the class
/// and the code-behind path.
///
/// Does not return null.
/// </summary>
public string ResolvePartialPath (Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
string partialPath;
if (resolvedPaths.TryGetValue(type, out partialPath))
{
return partialPath;
} else
{
string mappedPath;
if (MappedPartialPaths.TryGetValue(type, out mappedPath))
{
resolvedPaths[type] = mappedPath;
return mappedPath;
} else
{
// Since I use well-mapped virtual directory names to namespaces,
// this gets around needing to manually specify all the types above.
if (!type.FullName.StartsWith(BaseNamespace))
{
throw new InvalidOperationException("Invalid control type");
} else
{
var reflectionPath = type.FullName
.Replace(BaseNamespace, "")
.Replace('.', '/');
resolvedPaths[type] = reflectionPath;
return reflectionPath;
}
}
}
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
名称空间FooBar
{
类控制解析器
{
const string BaseNamespace=“TheBaseControlNameSpace”;
只读IDictionary ResolvedPath=new Dictionary();
///
///将类型映射到控件的部分路径。
///
///对于不能自动解析的类型,这是必需的
///通过简单的反射映射。
///
静态只读IDictionary MappedPartialPath=新字典
{
{typeof(myodtype),“Relative/ControlPath”},//No virtual~BASE,No.ASXC
};
///
///给定类型,返回ASCX的部分路径。
///
///此路径是控件模板根目录下的路径
///没有ASCX扩展。
///
///这是必需的,因为类之间没有维护映射
///以及代码隐藏路径。
///
///不返回null。
///
公共字符串ResolvePartialPath(类型)
{
if(type==null)
{
抛出新的ArgumentNullException(“类型”);
}
字符串部分路径;
if(ResolvedPath.TryGetValue(类型,out partialPath))
{
返回部分路径;
}否则
{
字符串映射路径;
if(MappedPartialPaths.TryGetValue(类型,out-mappedPath))
{
ResolvedPath[type]=mappedPath;
返回映射路径;
}否则
{
//因为我使用了映射良好的虚拟目录名到名称空间,
//这样就不需要手动指定上面的所有类型。
如果(!type.FullName.StartsWith(BaseNamespace))
{
抛出新的InvalidOperationException(“无效控件类型”);
}否则
{
var reflectionPath=type.FullName
.Replace(BaseNamespace,“”)
.替换(“.”、“/”);
ResolvedPath[type]=reflectionPath;
返回反射路径;
}
}
}
}
}
}
油井外壳。我担心这可能是最重要的case@Mr贝尔:不过,这确实值得一问。这个问题的标签是C,但这似乎是VB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace FooBar
{
class ControlResolver
{
const string BaseNamespace = "TheBaseControlNameSpace";
readonly IDictionary<Type, string> resolvedPaths = new Dictionary<Type, string>();
/// <summary>
/// Maps types to partial paths for controls.
///
/// This is required for Types which are NOT automatically resolveable
/// by the simple reflection mapping.
/// </summary>
static readonly IDictionary<Type, string> MappedPartialPaths = new Dictionary<Type, string>
{
{ typeof(MyOddType), "Relative/ControlPath" }, // No virtual ~BASE, no .ASXC
};
/// <summary>
/// Given a type, return the partial path to the ASCX.
///
/// This path is the path UNDER the Control Template root
/// WITHOUT the ASCX extension.
///
/// This is required because there is no mapping maintained between the class
/// and the code-behind path.
///
/// Does not return null.
/// </summary>
public string ResolvePartialPath (Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
string partialPath;
if (resolvedPaths.TryGetValue(type, out partialPath))
{
return partialPath;
} else
{
string mappedPath;
if (MappedPartialPaths.TryGetValue(type, out mappedPath))
{
resolvedPaths[type] = mappedPath;
return mappedPath;
} else
{
// Since I use well-mapped virtual directory names to namespaces,
// this gets around needing to manually specify all the types above.
if (!type.FullName.StartsWith(BaseNamespace))
{
throw new InvalidOperationException("Invalid control type");
} else
{
var reflectionPath = type.FullName
.Replace(BaseNamespace, "")
.Replace('.', '/');
resolvedPaths[type] = reflectionPath;
return reflectionPath;
}
}
}
}
}
}
' Load the control
Dim myUC as UserControl = LoadControl("ucHeading.ascx")
' Set the Usercontrol Type
Dim ucType as Type = myUC.GetType()
' Get access to the property
Dim ucPageHeadingProperty as PropertyInfo = ucType.GetProperty("PageHeading")
' Set the property
ucPageHeadingProperty.SetValue(myUC,"Access a Usercontrol from Code Behind",Nothing)
pnlHeading.Controls.Add ( myUC )