posts - 58,  comments - 121,  trackbacks - 30

在同一个页面上放置多个 DropDownList 或 ListBox ,不管这些列表控件的各自的选项是什么,只要设置了其中一个的选项是第几个,则其它所有的列表控件也同样受影响。请各位自己测试一下。

我的测试例子如下:
Default2.aspx
----------------------------------------------
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default2.aspx.cs" Inherits="Default2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>无标题页</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <asp:DropDownList ID="DropDownList1" runat="server"></asp:DropDownList>
    <asp:ListBox ID="ListBox1" runat="server"></asp:ListBox>
    </div>
    </form>
</body>
</html>
------------------------------------------



Default2.aspx.cs
------------------------------------------
using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;

public partial class Default2 : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            ListItem li1 = new ListItem();
            li1.Text = "选项一";
            li1.Value = "111";
            this.DropDownList1.Items.Add(li1);
            this.ListBox1.Items.Add(li1);

            ListItem li2 = new ListItem();
            li2.Text = "选项二";
            li2.Value = "222";
            this.DropDownList1.Items.Add(li2);
            this.ListBox1.Items.Add(li2);

            ListItem li3 = new ListItem();
            li3.Text = "选项三";
            li3.Value = "333";
            this.DropDownList1.Items.Add(li3);
            this.ListBox1.Items.Add(li3);

            ListItem li4 = new ListItem();
            li4.Text = "选项四";
            li4.Value = "444";
            this.DropDownList1.Items.Add(li4);
            this.ListBox1.Items.Add(li4);

            this.DropDownList1.SelectedValue = "333";
            this.ListBox1.SelectedValue = "222";

            //this.DropDownList1.SelectedIndex = 1;
        }
    }
}

------------------------------------------
我的本意是想DropDownList1默认选中的“选项三”,ListBox1默认选中的“选项二”,但是结果却都是“选项二”,大家也遇到过同样的问题吗?

posted on 2008-06-17 11:54 datasky 阅读(2434) 评论(43)  编辑 收藏 网摘 所属分类: ASP.NET

FeedBack:
#1楼 [楼主]
2008-06-17 12:03 | datasky      
如果你直接将选项写到页面上,而不是在代码里后添的,则不会出现这样的问题。
如修改一下上面的测试代码:
<asp:DropDownList ID="DropDownList1" runat="server">
<asp:ListItem Value="111">选项一</asp:ListItem>
<asp:ListItem Value="222">选项二</asp:ListItem>
<asp:ListItem Value="333">选项三</asp:ListItem>
<asp:ListItem Value="444">选项四</asp:ListItem>
</asp:DropDownList>
<asp:ListBox ID="ListBox1" runat="server">
<asp:ListItem Value="111">选项一</asp:ListItem>
<asp:ListItem Value="222">选项二</asp:ListItem>
<asp:ListItem Value="333">选项三</asp:ListItem>
<asp:ListItem Value="444">选项四</asp:ListItem>
</asp:ListBox>
------
//前面添加选项的注释掉
this.DropDownList1.SelectedValue = "333";
this.ListBox1.SelectedValue = "222";

  回复  引用  查看    
2008-06-17 12:03 | ciwei0709 [未注册用户]
应该是你使用了相同的ListItem,选中的话是ListItem的Selected属性被设为true,
而 DropDownList1 和 ListBox1 使用是的同一个 ListItem,所以两个都被选中。

  回复  引用    
#3楼 [楼主]
2008-06-17 12:05 | datasky      
@ciwei0709
难道.net认的仅仅是ListItem?
怎么样才能达到我的原意呢?
  回复  引用  查看    
2008-06-17 12:27 | NetSpirit [未注册用户]
我觉得你对基本的面向对象,引用等概念都不理解,不要随便就说是别人的bug,再仔细看看你的代码。
  回复  引用    
2008-06-17 12:31 | 曲滨*銘龘鶽      
你不知道.net 的很多对象都是按引用传递的?
你那些 ListItem 并不是被复制的;
  回复  引用  查看    
2008-06-17 12:42 | Gray Zhang      
了解下引用类型的概念吧
  回复  引用  查看    
2008-06-17 12:46 |       

写一个公用的方法: 
DropDownList和ListBox都继承自ListControl
protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            BindList(DropDownList1);
            BindList(ListBox1);
            this.DropDownList1.SelectedValue = "333";
            this.ListBox1.SelectedValue = "222";
        }
    }
    private void BindList(ListControl listControl)
    {
       
        ListItem li1 = new ListItem();
        li1.Text = "选项一";
        li1.Value = "111";
        listControl.Items.Add(li1);

        ListItem li2 = new ListItem();
        li2.Text = "选项二";
        li2.Value = "222";
        listControl.Items.Add(li2);

        ListItem li3 = new ListItem();
        li3.Text = "选项三";
        li3.Value = "333";
        listControl.Items.Add(li3);

        ListItem li4 = new ListItem();
        li4.Text = "选项四";
        li4.Value = "444";
        listControl.Items.Add(li4);
    }


  回复  引用  查看    
2008-06-17 12:54 | Dove.Net      
楼主自己的问题
  回复  引用  查看    
2008-06-17 13:01 | 第一控制.NET      
你先看看什么叫值类型,什么叫引用类型吧。基础中的基础。
  回复  引用  查看    
2008-06-17 13:11 | leafyoung [未注册用户]
个人感觉,从逻辑上看这段代码是完全没有问题的,即使DropDownList和ListBox共享所有的Item。

之所以出现楼主描述的这个现象,完全是由于<SELECT>这个HTML元素如何实现哪个元素被选中导致的。设置SelectedValue并不是在DropDownList或者ListBox设置了什么属性,而是在ListItem上做了“selected”标记,而ListItem在两个控件共享,所以选中的就是最后设置为SelectedValues的item了。

用reflector看一下SelectedValue属性是怎么做的就清楚了:
public virtual void set_SelectedValue(string value)
{
if (this.Items.Count != 0)
{
if ((value == null) || (base.DesignMode && (value.Length == 0)))
{
this.ClearSelection();
return;
}
ListItem item = this.Items.FindByValue(value);
if ((((this.Page != null) && this.Page.IsPostBack) && this._stateLoaded) && (item == null))
{
throw new ArgumentOutOfRangeException("value", SR.GetString("ListControl_SelectionOutOfRange", new object[] { this.ID, "SelectedValue" }));
}
if (item != null)
{
this.ClearSelection();
item.Selected = true; <-- here we go
}
}
this.cachedSelectedValue = value;
}


  回复  引用    
2008-06-17 13:17 | 游民一族      
所以,这个问题不是bug,不过也不是楼主的错,确实很容易引起混淆的说,可以说是HTML界面元素为了模仿控件的一点小小代价

  回复  引用  查看    
2008-06-17 13:21 | henry      
@NetSpirit
@第一控制.NET
@曲滨*銘龘鶽
如果我在一个button event里设置SelectedValue 结果是不楼主那样?
  回复  引用  查看    
#13楼 [楼主]
2008-06-17 13:23 | datasky      
@NetSpirit
@曲滨*銘龘鶽
@Gray Zhang
@第一控制.NET
还真没有深入的研究过值类型和引用类型,决定认真看一下。

@游民一族(leafyoung)
非常感谢您的分析。
  回复  引用  查看    
#14楼 [楼主]
2008-06-17 13:24 | datasky      
@瞬
谢谢您给出的解决办法。
  回复  引用  查看    
#15楼 [楼主]
2008-06-17 13:32 | datasky      
@henry
按照楼上几位的说法理解,只要你的ListItem不是一起设置的,而仅仅只是同时设置了几个列表控件的SelectedValue 属性,应该是没有关系的。
  回复  引用  查看    
#16楼 [楼主]
2008-06-17 13:48 | datasky      
@瞬
有的时候,我需要将一个数据集里面相同的选项同时绑定给多个不同的ListControl,那只能进行多次单独的绑定了?
  回复  引用  查看    
2008-06-17 14:07 | duxer      
ListItem li1 = new ListItem();
li1.Text = "选项一";
li1.Value = "111";
listControl.Items.Add(li1);

li1 = new ListItem();
li1.Text = "选项二";
li1.Value = "222";
listControl.Items.Add(li1);

li1 = new ListItem();
li1.Text = "选项三";
li1.Value = "333";
listControl.Items.Add(li1);

li1 = new ListItem();
li1.Text = "选项四";
li1.Value = "444";
listControl.Items.Add(li1);

这种方法试一下呢
  回复  引用  查看    
2008-06-17 14:10 | willieQ      
10楼分析很深入~~~~学习
  回复  引用  查看    
#19楼 [楼主]
2008-06-17 14:16 | datasky      
@duxer
您的代码其实是一回事,关键您是要替换哪一部分呢?
如果是我原文中的对应的代码,则还会出现。
如果是 @瞬 的BindList ,则不会出现。
  回复  引用  查看    
#20楼 [楼主]
2008-06-17 14:17 | datasky      
@willieQ
呵呵!10楼的 leafyoung 其实就是 11楼的 游民一族 。

  回复  引用  查看    
2008-06-17 14:26 | 风海迷沙      
为了说不是才进来看的
  回复  引用  查看    
#22楼 [楼主]
2008-06-17 14:40 | datasky      
@风海迷沙
呵呵!为何不用您更精到的词汇讲讲您是怎么理解这个现象的呢?
  回复  引用  查看    
2008-06-17 15:02 | henry      
@datasky
主要那情况是这样,一旦post后从viewstate还原他们就已经是不同的object
  回复  引用  查看    
2008-06-17 15:17 | 暗香浮动      
唉。
  回复  引用  查看    
#25楼 [楼主]
2008-06-17 15:39 | datasky      
@henry
那您测试一下呢?

@暗香浮动
更愿意听到您的高见。
  回复  引用  查看    
2008-06-17 16:44 | efreer [未注册用户]
楼主先看看自己的屁股吧!
  回复  引用    
2008-06-17 16:49 | Liquidream [未注册用户]
10楼正解!

当你
this.DropDownList1.SelectedValue = "333";
this.ListBox1.SelectedValue = "222";

在服务端DropDownList1和ListBox1两个控件的Item共同指向你New的四个ListItem,最后一句代码选择了同一个ListItem, 当发送到客户端的HTML代码就使得两个控件选择同样的Index。

楼主没有理解引用类型和值类型概念。



  回复  引用    
#28楼 [楼主]
2008-06-17 16:53 | datasky      
@efreer
^_^ 您真风趣。

@Liquidream
非常感谢您的指点。
  回复  引用  查看    
2008-06-17 17:05 | Flymouse      
--引用--------------------------------------------------
ciwei0709: 应该是你使用了相同的ListItem,选中的话是ListItem的Selected属性被设为true,
而 DropDownList1 和 ListBox1 使用是的同一个 ListItem,所以两个都被选中。

--------------------------------------------------------
对,就是他说的这个原因
  回复  引用  查看    
2008-06-17 17:14 | 颜昌钢      
两个控件 都用的同一个 ListItem
当然会这样...
  回复  引用  查看    
2008-06-17 17:18 | henry      
@datasky
具备了状态管理的对象都实现了IStateManager.
SaveState信息保存,而LoadState信息获取(这样东西会序列化保存到一个input里)当page post back后,所有控件状态信息都从自身的loadstate还源.
page load代码里的确是指同一个对象导致,一旦经过post back后即使同一个事件里设置两个selectvalue是不会出现你的情况的.


  回复  引用  查看    
2008-06-17 17:23 | Ants      
.net的门槛太低还会有这样的低级错误.
多补下基本功吧。。不然永远都没有进步
  回复  引用  查看    
#33楼 [楼主]
2008-06-17 17:25 | datasky      
@Flymouse
@颜昌钢
呵呵!现在明白了!

@Ants
我以为DropDownList 或 ListBox 会自动处理好这件事情的。
如您所说,是该巩固一下基础和研究一下底层了。

@henry
谢谢您的分享!
  回复  引用  查看    
2008-06-17 17:38 |       

datasky:将一个数据集里面相同的选项同时绑定给多个不同的ListControl
是不是这样:先封做一个ItemAdd方法.在这个方法中.new一个ListItem.再处理..变相做一下赋值..我可能理解的不太对..
 
protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            ListItem li1 = new ListItem();
            li1.Text = "选项一";
            li1.Value = "111";
            ItemAdd(DropDownList1, li1);
            ItemAdd(ListBox1, li1);

            ListItem li2 = new ListItem();
            li2.Text = "选项二";
            li2.Value = "222";
            ItemAdd(DropDownList1, li2);
            ItemAdd(ListBox1, li2);

            ListItem li3 = new ListItem();
            li3.Text = "选项三";
            li3.Value = "333";
            ItemAdd(DropDownList1, li3);
            ItemAdd(ListBox1, li3);

            ListItem li4 = new ListItem();
            li4.Text = "选项四";
            li4.Value = "444";
            ItemAdd(DropDownList1, li4);
            ItemAdd(ListBox1, li4);

            this.DropDownList1.SelectedValue = "333";
            this.ListBox1.SelectedValue = "222";

        }
    }
    private void ItemAdd(ListControl listControl,ListItem oldLi)
    {
        ListItem newLi = new ListItem(oldLi.Text,oldLi.Value);
        listControl.Items.Add(newLi);
    }


  回复  引用  查看    
2008-06-17 17:41 | 我是来打酱油的 [未注册用户]
--引用--------------------------------------------------
NetSpirit: 我觉得你对基本的面向对象,引用等概念都不理解,不要随便就说是别人的bug,再仔细看看你的代码。
--------------------------------------------------------

很正常,初学者的通病就是遇到问题常常怪编译器有毛病,呵呵!
  回复  引用    
2008-06-17 17:53 | Windie Chai(笑煞天)      
“引用”啊兄弟
  回复  引用  查看    
2008-06-17 19:54 | 于雷 [未注册用户]
ListItem可以被看做一个对象,你再添加的时候是被引用到list里面的
所以你操作两个list控件中的项时,其实是操作了同一个对象

可以使用 listControl.Items.Add(new ItemList("asd","sdf"));

方法来做
  回复  引用    
2008-06-17 20:47 | 编织套管 [未注册用户]
问个问题算是bug。
  回复  引用    
2008-06-17 20:54 | bangbang [未注册用户]
博主应该是没搞清楚引用类型的特点。博主这样的添加方法,同一个ListItem被加到两个控件里面去了,一边的改了,另外一边自然也改了。同样的情况,如果把同一个数据源绑定不同的控件上,也是会出现这种情况的。
  回复  引用    
2008-06-18 00:00 | 远航1 [未注册用户]
呵呵,看来楼主对引用类型与值类型不太了解呀!
  回复  引用    
2008-06-18 10:12 | 丁一      
支持楼主,
将ListItem添加到Items集合之前他没有设置其中某项的Selected属性为true.
添加完之后才 this.DropDownList1.SelectedValue = "333";
楼主的意图很明确,
是想设置值为"333"的项为 DropDownList1 的当前选择项.

而不幸的是, SelectedValue 是直接操作 Items 集合的. (恰巧这个集合中的项在其它控件中也被引用了)
public virtual string SelectedValue{
get{...}
set{
..
ListItem item = this.Items.FindByValue(value);
if (item != null) {
this.ClearSelection();
item.Selected = true;
}
..
}

一个很明确的问题是 "我操作DropDownList1的SelectedValue关ListBox1屁事".

所以我觉得应该算是.net设计上的一个小污点.

"假想"..
-------------------------------------------

public abstract class ListControl : DataBoundControl, IEditableTextControl, ITextControl
{
..
private string[] _values = null;
public virtual string[] SelectValues {
get{ return _values; }
set{ _values = value;}
}

protected override void Render(HtmlTextWriter writer) {
..
// 检查 _values, 并根据 _values 中的值设置输出HTML.
..
}
..
}

并将 ListItem Selected 属性去除.

-------------------------------------------
以上仅是一个菜鸟的观点, 各位"下手"轻些..


  回复  引用  查看    
2008-06-18 10:33 | 乱侃      
明白了什么是值类型,什么是引用类型,上面的代码就不难理解为什么为这样了
虽然写的是托管代理,但是我觉得对于指针的理解还是不能放弃的
  回复  引用  查看    
#43楼 [楼主]
2008-06-18 10:40 | datasky      
@ 丁一
感谢您更生动的分析。

◎all
虽然现在是知道原因了,知道为什么会这样了。
最后我个人还是觉得.net的DropDownList 或 ListBox 应该自动做好这个工作。
按照 NetSpirit 的说法,真的面向对象的话,我觉得我指定的是DropDownList 的选定项而不是 ListBox 的选定项,就算你两个人内部是一样的,那是你内部的事情,但是当你展现出来给浏览者的时候还是应该各归各的。如果我指定了某个ListItem的选定属性,然后再绑给多个列表控件的话,这时候多个列表控件选中同一个选项就是理所当然的了。
欢迎各位发表自己的看法!
  回复  引用  查看    

标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2008-06-17 11:58 编辑过
Google站内搜索


China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!

相关文章:


相关搜索:
ListBox DropDownList bug

相关链接:


 

欢迎加入Asp.net高手MSN群

  • asp.net.group#hotmail.com
  • asp.net_group#hotmail.com

与我联系

搜索

 

常用链接

留言簿

我管理的小组

我的标签

随笔分类(71)

相册

blogs链接

积分与排名

  • 积分 - 35317
  • 排名 - 1299

最新评论