VS 2008,ASP.NET:生成本地资源 [英] VS 2008, ASP.NET: Generate Local Resources

查看:78
本文介绍了VS 2008,ASP.NET:生成本地资源的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经建立了一个简单的控件,叫做Menu:

  namespace MyControls 
{
public class MenuItem
{
public MenuItem()
{
Visible = true;
}

[Localizable(true)]
公共字符串Text {get;组; }
[Localizable(false)]
公共字符串Link {get;组; }
[DefaultValue(true)]
public bool可见{get;组; }
}

公共类MenuDesigner:System.Web.UI.Design.ControlDesigner
{
...
}

[ParseChildren(true, Items)]
[PersistChildren(false)]
[Designer(typeof(MenuDesigner))]
公共类菜单:控件
{
...

public Menu()
{
}

...

私人清单< MenuItem> _items = new List< MenuItem>();
[PersistenceMode(PersistenceMode.InnerProperty)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public List< MenuItem>项目
{
获得
{
return _items;
}
}

受保护的覆盖无效OnPreRender(EventArgs e)
{
base.OnPreRender(e);

... //更多控件。

list = new BulletedList();
list.DisplayMode = BulletedListDisplayMode.HyperLink;
this.Controls.Add(list);

foreach(_items中的var mi)
{
list.Items.Add(new ListItem(mi.Text,Page.Request.CreateUrl(mi.Link))));
}
}
}
}

I

 < my:Menu ID = menu runat = server Text = MenuTitle> 
< my:MenuItem Text = text Link = link1.aspx>
< / my:MenuItem>
< my:MenuItem Text = text2 Link = link2.aspx>
< / my:MenuItem>
< / my:Menu>

这有效。没问题。当我切换到Designer视图时,以MenuDesigner呈现控件的方式看到控件。用CTRL-K重新进行格式化,CTRL-D可以正常工作。运行我的WebPage将按我期望的方式呈现给Menu。



但是:当我在DesingView中单击菜单项工具->生成本地资源时,会得到以下结果:

 < my:Menu ID = menu runat = server Text = MenuTitle 
meta:resourcekey = menuResource9>
< my:MenuItem Text = text Link = link1.aspx>
< / my:MenuItem>
< my:MenuItem Text = text2 Link = link2.aspx>
< / my:MenuItem>
< Items>
< my:MenuItem Text = text Link = link1.aspx meta:resourcekey = MenuItemResource10>< / my:MenuItem>
< my:MenuItem Text = text2 Link = link2.aspx meta:resourcekey = MenuItemResource11>< / my:MenuItem>
< / Items>
< / my:Menu>

缺少哪个属性?我已经研究了ListBox,它也解析子项,我觉得我的控件也是如此。



我发现的唯一区别是:




  • 我使用的是通用列表,ListBox具有它自己的ListItems集合类型

  • 我没有编辑器



这不是我要出售的MenuItem,而是ControlBoxer或TypeConverter。 。我不需要任何编辑器或Desinger,我正在手工编写HTML / ASP.NET标记。



我正在使用Visual Studio 2008,.NET 3.5。 / p>

感谢任何提示,帮助或解决方案!

解决方案

IMO,您的代码不正确。因为,您没有在 MenuItem 中实现 IStateManager 。在这种情况下,通用列表也不是有效的类型。您必须编写一个实现 IStateManager 的自定义集合,或使用 StateManagedCollection



MenuItem

 公共类MenuItem :IStateManager 
{

private StateBag _viewState;
私人布尔值_isTrackingViewState;

公共字符串文本
{
get {return(string)ViewState [ Text]? string.Empty; }
set {ViewState [ Text] =值; }
}

public void SetDirty()
{
if(this._viewState!= null)
this._viewState.SetDirty(true);
}

受保护的虚拟StateBag ViewState
{
get
{
if(this._viewState == null)
{
this._viewState = new StateBag(true);
if(this._isTrackingViewState)
((IStateManager)this._viewState).TrackViewState();
}
返回this._viewState;
}
}

bool IStateManager.IsTrackingViewState
{
get {返回this._isTrackingViewState; }
}

void IStateManager.LoadViewState(对象状态)
{
if(state!= null)
((IStateManager)this.ViewState) .LoadViewState(state);
}

对象IStateManager.SaveViewState()
{
if(this._viewState!= null)
return((IStateManager)this._viewState) .SaveViewState();
返回null;
}

void IStateManager.TrackViewState()
{
this._isTrackingViewState = true;

if(this._viewState!= null)
((IStateManager)this._viewState).TrackViewState();
}

}

MenuItemCollection >

 公共类MenuItemCollection:StateManagedCollection 
{

public MenuItem this [int index]
{
get {return(MenuItem)((IList)this)[index]; }
}

public int Add(MenuItem item)
{
return((IList)this).Add(item);
}

public void Remove(MenuItem item)
{
((IList)this).Remove(item);
}

//编写Insert和RemoveAt方法

受保护的重写void SetDirtyObject(object o)
{
((MenuItem)o ).SetDirty();
}

}

菜单

  [ParseChildren(true, Items),PersistChildren(false)] 
公共类菜单:控制
{

private MenuItemCollection _items;

[PersistenceMode(PersistenceMode.InnerDefaultProperty),MergableProperty(false)]
public MenuItemCollection项目
{
获得
{
if(this ._items == null)
{
this._items = new MenuItemCollection();
if(base.IsTrackingViewState)
((IStateManager)this._items).TrackViewState();
}
返回this._items;
}
}

受保护的覆盖无效TrackViewState()
{
base.TrackViewState();

if(this._items!= null)
((IStateManager)this._items).TrackViewState();
}

受保护的重写void LoadViewState(object savedState)
{
对状态=(对)savedState;

base.LoadViewState(states.First);

if(states.Second!= null)
((IStateManager)this.Items).LoadViewState(states.Second);
}

受保护的覆盖对象SaveViewState()
{
配对状态=新的Pair();

States.First = base.SaveViewState();

if(this._items!= null)
状态。Second =(((IStateManager)this._items).SaveViewState();

返回状态;
}

}

注意:我没有测试上面的代码。



无论如何,在我的选择之前,还有一个答案是正确的,但已被删除。您已将项目属性的 PersistenceMode 设置为 InnerProperty 。因此,您必须按如下方式编写标记。

 < my:Menu ID = menu runat = server文本= MenuTitle> 
< Items>
< my:MenuItem Text = text Link = link1.aspx />
< my:MenuItem Text = text2 Link = link2.aspx />
< / Items>
< / my:Menu>


I've build an simple control called Menu:

namespace MyControls
{
    public class MenuItem
    {
        public MenuItem()
        {
            Visible = true;
        }

        [Localizable(true)]
        public string Text { get; set; }
        [Localizable(false)]
        public string Link { get; set; }
        [DefaultValue(true)]
        public bool Visible { get; set; }
    }

    public class MenuDesigner : System.Web.UI.Design.ControlDesigner
    {
        ...
    }

    [ParseChildren(true, "Items")]
    [PersistChildren(false)]
    [Designer(typeof(MenuDesigner))]
    public class Menu : Control
    {
        ...

        public Menu()
        {
        }

        ...

        private List<MenuItem> _items = new List<MenuItem>();
        [PersistenceMode(PersistenceMode.InnerProperty)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public List<MenuItem> Items
        {
            get
            {
                return _items;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e); 

            ... // More Controls.

            list = new BulletedList();
            list.DisplayMode = BulletedListDisplayMode.HyperLink;
            this.Controls.Add(list);

            foreach (var mi in _items)
            {
                list.Items.Add(new ListItem(mi.Text, Page.Request.CreateUrl(mi.Link)));
            }
        }
    }
}

I use it in my Page this way:

    <my:Menu ID="menu" runat="server" Text="MenuTitle">
        <my:MenuItem Text="text" Link="link1.aspx">
        </my:MenuItem>
        <my:MenuItem Text="text2" Link="link2.aspx">
        </my:MenuItem>
    </my:Menu>

This works. No Problems. When I switch to the Designer View I see the Control in the way my MenuDesigner renders it. Reformating with CTRL-K, CTRL-D works. Running my WebPage renders to Menu the way I expected it.

But: when I hit in the DesingView the Menu Item "Tools" -> "Generate Local Resource" I get this result:

<my:Menu ID="menu" runat="server" Text="MenuTitle" 
            meta:resourcekey="menuResource9">
            <my:MenuItem Text="text" Link="link1.aspx">
            </my:MenuItem>
            <my:MenuItem Text="text2" Link="link2.aspx">
            </my:MenuItem>
            <Items>
<my:MenuItem Text="text" Link="link1.aspx" meta:resourcekey="MenuItemResource10"></my:MenuItem>
<my:MenuItem Text="text2" Link="link2.aspx" meta:resourcekey="MenuItemResource11"></my:MenuItem>
</Items>
        </my:Menu>

Which Attributes are missing/wrong? I've looked into ListBox, which also parses child items an I have the feelding that my control is doing the same.

The only differences I've found:

  • I am using a generic List, ListBox has it's own collection type for ListItems
  • I have no Editor or ControlBuilder or TypeConverter for my MenuItem, ListBox does.

This is not a control I'm willing to sell, it's only for me. I don't need any Editor or Desinger, I'm writing HTML/ASP.NET markup by hand.

I am using Visual Studio 2008, .NET 3.5.

Thanks for any Hints, Help or Sulutions!

解决方案

IMO, your code is incorrect. Because, you didn't implement IStateManager in the MenuItem. Also generic list is not a valid type in this case. You have to write a custom collection that implements IStateManager or use StateManagedCollection.

MenuItem

public class MenuItem : IStateManager
{

    private StateBag _viewState;
    private bool _isTrackingViewState;

    public string Text
    {
        get { return (string)ViewState["Text"] ?? string.Empty; }
        set { ViewState["Text"] = value; }
    }

    public void SetDirty()
    {
        if (this._viewState != null)
            this._viewState.SetDirty(true);
    }

    protected virtual StateBag ViewState
    {
        get
        {
            if (this._viewState == null)
            {
                this._viewState = new StateBag(true);
                if (this._isTrackingViewState)
                    ((IStateManager)this._viewState).TrackViewState();
            }
            return this._viewState;
        }
    }

    bool IStateManager.IsTrackingViewState
    {
        get { return this._isTrackingViewState; }
    }

    void IStateManager.LoadViewState(object state)
    {
        if (state != null)
            ((IStateManager)this.ViewState).LoadViewState(state);
    }

    object IStateManager.SaveViewState()
    {
        if (this._viewState != null)
            return ((IStateManager)this._viewState).SaveViewState();
        return null;
    }

    void IStateManager.TrackViewState()
    {
        this._isTrackingViewState = true;

        if (this._viewState != null)
            ((IStateManager)this._viewState).TrackViewState();
    }

}

MenuItemCollection

public class MenuItemCollection : StateManagedCollection
{

    public MenuItem this[int index]
    {
        get { return (MenuItem)((IList)this)[index]; }
    }

    public int Add(MenuItem item)
    {
        return ((IList)this).Add(item);
    }

    public void Remove(MenuItem item)
    {
        ((IList)this).Remove(item);
    }

    // Write Insert and RemoveAt methods

    protected override void SetDirtyObject(object o)
    {
        ((MenuItem)o).SetDirty();
    }

}

Menu

[ParseChildren(true, "Items"), PersistChildren(false)]
public class Menu : Control
{

    private MenuItemCollection _items;

    [PersistenceMode(PersistenceMode.InnerDefaultProperty), MergableProperty(false)]
    public MenuItemCollection Items
    {
        get
        {
            if (this._items == null)
            {
                this._items = new MenuItemCollection();
                if (base.IsTrackingViewState)
                    ((IStateManager)this._items).TrackViewState();
            }
            return this._items;
        }
    }

    protected override void TrackViewState()
    {
        base.TrackViewState();

        if (this._items != null)
            ((IStateManager)this._items).TrackViewState();
    }

    protected override void LoadViewState(object savedState)
    {
        Pair states = (Pair)savedState;

        base.LoadViewState(states.First);

        if (states.Second != null)
            ((IStateManager)this.Items).LoadViewState(states.Second);
    }

    protected override object SaveViewState()
    {
        Pair states = new Pair();

        states.First = base.SaveViewState();

        if (this._items != null)
            states.Second = ((IStateManager)this._items).SaveViewState();

        return states;
    }

}

Note: I didn't test the above code.

Anyway, there was another answer before mine that was correct in my opition, but has been deleted. You have set the PersistenceMode of Items property to InnerProperty. Thus, you have to write markup as follows.

<my:Menu ID="menu" runat="server" Text="MenuTitle">
    <Items>
        <my:MenuItem Text="text" Link="link1.aspx" />
        <my:MenuItem Text="text2" Link="link2.aspx" />
    </Items>
</my:Menu>

这篇关于VS 2008,ASP.NET:生成本地资源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆