如何根据类型加载用户控件

如果你有类型(即
typeof(MyUserControl)
),有没有办法实例化和使用usercontrol(.ascx)? 使用常规的asp.net控件(如文本框或下拉列表),您只需创建一个新实例并将其添加到控件集合中。这似乎不适用于用户控件。虽然您可以创建一个新实例并将其添加到集合中,并且触发所有事件,但它实际上不会呈现给页面。通常,您可以使用.ascx的路径调用
Page.LoadControl()
如果只有它的类型,这就会出现问题。你怎么能得到.ascx的路径来给
LoadControl
方法。理想情况下,我还希望不必引用Page对象     
已邀请:
不,这是不可能的;必须提供ASCX虚拟路径以使用标记动态加载用户控件,并且没有虚拟路径类型的内部映射。 但是,因为我仍然很懒,所以我使用的方法仍然是“类型安全”,并将解决问题隔离到代码中的单个位置。它仍然需要访问“页面对象”,否则会处理愚蠢的细节。 以下是简要说明: 使用类型查找相对(到我的根)ASCX路径,使用启发式将类型从命名空间映射到虚拟路径;允许一种指定手动映射的方法,并在指定时使用它 将类型的相对路径转换为正确/完整的虚拟路径 使用虚拟路径加载控件 继续,好像什么也没发生过 享受(我只是从我的项目中复制'n'pasted选择部分,YMMV):
    /// <summary>
    /// Load the control with the given type.
    /// </summary>
    public object LoadControl(Type t, Page page)
    {
        try
        {
            // The definition for the resolver is in the next code bit
            var partialPath = resolver.ResolvePartialPath(t);
            var fullPath = ResolvePartialControlPath(partialPath);
            // Now we have the Control loaded from the Virtual Path. Easy.
            return page.LoadControl(fullPath);
        } catch (Exception ex)
        {
            throw new Exception("Control mapping failed", ex);
        }
    }

    /// <summary>
    /// Loads a control by a particular type.
    /// (Strong-typed wrapper for the previous method).
    /// </summary>
    public T LoadControl<T>(Page page) where T : Control
    {
        try
        {
            return (T)LoadControl(typeof (T), page);
        } catch (Exception ex)
        {
            throw new Exception(string.Format(
                "Failed to load control for type: {0}",
                typeof (T).Name), ex);
        }
    }

    /// <summary>
    /// Given a partial control path, return the full (relative to root) control path.
    /// </summary>
    string ResolvePartialControlPath(string partialPath)
    {
        return 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;
                    }
                }
            }
        }
    }
}
    
你可能在这里运气不好。 这个家伙无法得到这方面的帮助。 他们告诉这个人不能这样做。     

要回复问题请先登录注册