有这样一个自定义控件,在同一个页面上它的某个属性必须彼此不同,否则就会在最终生成的HTML上面引发错误。我想做到当开发者从toolbox把控件拖到页面上的时候该控件能自动检查该页面上的其他同类控件,从而选择一个尚未使用的值给那个属性赋值,有点类似控件的ID,每次添加一个控件的时候ID会从Ctr1变成Ctr2等等。但是该如何做呢?之前的一种做法
        [Bindable(true)]
        [Category("Custom")]
        [DefaultValue("1")]
        [Localizable(true)]
        public int StepIndex
        {
            get
            {
                int index = 1;
                if (ViewState["StepIndex"] != null)
                {
                    index = (int)ViewState["StepIndex"];
                }
                else
                {
                    if (HttpContext.Current == null)
                    {
//循环遍历Page上的所有同类控件,并选择一个尚未使用的值给其赋值。假设其为10
index = 10;
                    }
                }
                return index;
            }            set
            {
                ViewState["StepIndex"] = value;
            }
        }这么做之后在属性窗口里的确能看到该属性的默认值在自动增加,但是在察看aspx源码的时候却只能看到<cc1:MyControl ID="MyControl1" runat="server"></cc1:MyControl>,该属性并没有被真正赋值。之后在该类的ToolboxData里面写了[ToolboxData("<{0}:MyControl runat=Server StepIndex='1'></{0}:MyControl >")]。发现这么做之后,当拖控件进页面的时候,该属性(StepIndex)的值被固定在1上了,之前写的检测和赋值代码没有发挥作用。谁能帮忙看看吗?谢谢!

解决方案 »

  1.   

    否则就会在最终生成的HTML上面引发错误。
    ==========
    要从这里入手,为什么会产生错误?肯定会有解决办法的
      

  2.   

    javascript错误
    那个属性实际上是定义了一套执行顺序,按规矩来说是输入1,2,3就好,但是使用者总是忘记输入,结果在输出到最终HTML的时候就报javascript错,最后找上我说这个做的不好,要改进到上面说的自动更新的那种。
      

  3.   

    如果只要不重复很简单用个Guid就可.另外这个控件的ID也是不重复的.根据这个控件的ID后面加后缀生成属性也行.
      

  4.   

    另外这个控件的ID也是不重复的.根据这个控件的ID后面加后缀生成属性也行.
    =====>
    ClientID
      

  5.   

    用什么方法问题不大,总归是有办法的。但是麻烦的是,在设计时生成的这个属性,没法真正赋值给这个控件。“这么做之后在属性窗口里的确能看到该属性的默认值在自动增加,但是在察看aspx源码的时候却只能看到<cc1:MyControl ID="MyControl1" runat="server"></cc1:MyControl>,该属性并没有被真正赋值。”最后在run time的时候,依然只能取得默认值1。
      

  6.   

    if (HttpContext.Current == null)
                        {
    //循环遍历Page上的所有同类控件,并选择一个尚未使用的值给其赋值。假设其为10
    index = 10;
                        }==========
    因为这个代码就是设计时才运行.
      

  7.   

    是啊,这段代码就是让他在设计时才运行。我期望这个属性随着每拖入一个控件就会自动增加。如果已经给这个属性手动赋值,那么该手动赋的值优先。在run time的时候则不去遍历页面,遍历页面来赋值有可能会产生一些困惑。
      

  8.   

    简单解释一下,虽然我觉得这个和主题无关。
    这个控件在HTML上对应了一个JavaScript控件,这个控件的若干属性就是那个js对象的若干属性。如果那些个js对象的某个属性不唯一,就会出现js错误。
      

  9.   

    ASP.NET 2.0的架构已经允许你插手其页面分析与编译工作,你一定要获取Control.UniqueID或ClientID那样就必须要在编译前一个动手。你可以设计一个自定义的BuildProvider,这个BuildProvider专门负责检测这些控件并且为它们分配顺序值,这个值是保存到编译结果里面的。然后通过web.config配置你的项目加载这个BuildProvider。这时候此属性就享受UniqueID等同的待遇了。
      

  10.   

    所以在写控件时,最好不要直接操作客户端的id要用相对位置操作.或者利用server控件的clientid操作.
      

  11.   

    重点是,你是不是一定要把问题搞到那么复杂,非用BuildProvider不可。如果不是,可以考虑其他备选方案:1.用UniqueID的Hash结果来做默认值,理论上冲突概率非常低。2.通过改变客户端代码,避开唯一性要求。3.在使用此控件的页面上,一定要放一个Manager控件来协调它们的冲突。这是最轻量级而可靠的做法了。WebPartManager是一个例子,Atlas中的ClientScriptManager也是。而你的控件就好像WebPartZone或UpdatePanel那样,PreRender前页面内没有唯一一个Manager就throw吧。
      

  12.   

    To: cat_hsfz
    能给个参考文献么?
      

  13.   

    除了使用Manager或者BuildProvider控件就没有办法实现类似ID可以自动更新的办法了吗?我不要求在编译或run time的时候一定会出现run time error,而只要求在将控件拖入页面的时候那个值可以出现一个不重复的值,这样可以降低使用者出错的概率就可以了。之前还作了另外一种尝试,就是重写Render函数,在design time的时候检测那个属性是否有重复,如果有的话输出提示信息。但是不知道是不是因为该控件继承了INamingContainer接口,提示信息无法输出(同样的代码在没有继承INamingContainer接口的控件上可以起到正确的效果)。
      

  14.   

    继承ControlDesigner类,
    在Initialize(  IComponent component );函数里处理 component 就是你的控件实例
    可以通过它取得当前控件的属性
    再通过
    ComponentCollection documentComponents =                this.Component.Site.Container.Components;
    获得设计时页面所有元素分析
      

  15.   

    To hdt(倦怠)
    按照你的做法已经能成功取到该控件的属性,设置这个属性后在该控件的property窗口中看到该属性的确已经被设置成功。然而察看aspx源码的时候看到那个属性还是没有被设置,还是<cc1:MyControl ID="MyControl1" runat="server"></cc1:MyControl>,即该属性并没有被真正赋值。这个该如何解决?
      

  16.   

    Click the link to solve your problem.Good luck!