Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/274.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何加载给定类型的用户控件_C#_Asp.net_Dynamic Usercontrols - Fatal编程技术网

C# 如何加载给定类型的用户控件

C# 如何加载给定类型的用户控件,c#,asp.net,dynamic-usercontrols,C#,Asp.net,Dynamic Usercontrols,如果给定用户控件(.ascx)的类型(即typeof(MyUserControl)),是否有方法实例化和使用它 使用常规asp.net控件(如textbox或dropdownlist),您只需创建一个新实例并将其添加到控件集合中即可。这似乎不适用于用户控件。虽然您可以创建一个新实例并将其添加到集合中,并触发其所有事件,但它实际上不会呈现到页面中。通常,您会使用.ascx的路径调用Page.LoadControl() 如果您所拥有的只是它的类型,那么这就出现了一个问题。如何获取.ascx的路径以提

如果给定用户控件(.ascx)的类型(即
typeof(MyUserControl)
),是否有方法实例化和使用它

使用常规asp.net控件(如textbox或dropdownlist),您只需创建一个新实例并将其添加到控件集合中即可。这似乎不适用于用户控件。虽然您可以创建一个新实例并将其添加到集合中,并触发其所有事件,但它实际上不会呈现到页面中。通常,您会使用.ascx的路径调用
Page.LoadControl()


如果您所拥有的只是它的类型,那么这就出现了一个问题。如何获取.ascx的路径以提供给
LoadControl
方法。理想情况下,我也希望不必引用页面对象

您可能在这里运气不好

无法获得执行此操作的帮助


他们说这是不可能的。

不。这是不可能的;必须提供ASCX虚拟路径以动态加载带有标记的用户控件,并且没有虚拟路径类型的内部映射

然而,因为我仍然很懒惰,所以我使用的方法仍然是“类型安全”的,并将解决问题隔离到代码中的单个位置。它仍然需要访问“页面对象”,但在其他方面需要处理愚蠢的细节

以下是简要说明:

  • 使用类型查找相对(我的根)ASCX路径,使用启发式方法将类型从名称空间映射到虚拟路径;允许指定手动映射的方法,如果指定,请使用该方法
  • 将类型的相对路径转换为正确/完整的虚拟路径
  • 使用虚拟路径加载控件
  • 继续,就好像什么都没发生一样
  • 享受(我只是从我的项目中复制“n”粘贴的部分,YMMV):

    //
    ///使用给定类型加载控件。
    /// 
    公共对象加载控件(类型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 )