我们目前有一个标准多选功能的表单“这里有可用选项,这里是选定的选项,这里有一些按钮来回移动东西。”但是,客户现在希望不仅可以选择某些项目,还可以对它们进行分类。例如,给定书籍清单,他们不仅要选择他们拥有的书籍,还要选择他们阅读的书籍,他们想要阅读的书籍以及他们听过的书籍。 (所有示例都是虚构的。)值得庆幸的是,所选项目一次只能在一个类别中。
我可以找到许多在列表框之间移动项目的示例,但没有一个用于在多个列表框之间移动项目的示例。要添加到复杂功能,表单需要有两组列表+类别,例如除上述书籍外还需要分类的电影列表。
编辑:现在实际上坐下来尝试编写非javascripty位,我需要修改我的问题,因为我意识到多个选择列表不会真正起作用“如何通知服务器所有这个可爱的新信息“立场。所以html代码现在是一个伪列表框,即带有滚动条的框中显示的无序列表(<ul>
),每个列表项(<li>
)都有一组五个单选按钮(未选中) /自己/读取/像/听到)。
我的任务仍然大致相同:如何使用这一个列表并轻松对项目进行分类,以便用户可以一目了然地了解哪个类别。 (伪列表框与多选列表框有一些相同的缺点,即如果列表足够长以滚动,很难说出选择了什么。)梦想的解决方案是拖放类型的东西,但是在这一点上,甚至按钮都可以。
另一个修改(一个好的修改)是客户修改了列表,因此最长的是“仅”62个项目(而不是之前的数百个)。这些类别仍将主要包含零个,一个或两个选定项目,如果用户过于热心,可能会多一些。
对于操作系统和东西,该网站是经典的asp(退出窃笑!),服务器端代码是VBScript,到目前为止,我们通过几乎从不使用客户端的简单权宜之计避免了各种Javascript库脚本编写。这个客户的这种形式目前是一个很大的例外。给他们一英寸,他们想要一英里......
哦,我必须补充一点:我很喜欢Javascript,或者真的使用任何C后代语言。卷曲括号给我荨麻疹。我真的非常喜欢我可以复制的东西。粘贴到我的页面,可能会调整一些变量名称,而不会再次查看它。一个女孩可以做梦,不是吗? :)
[删除现有代码,因为它基本上无关紧要。]
答案 0 :(得分:1)
好笑,我也是,就在昨天用谷歌搜索“在多个列表框之间移动项目”并弹出你的问题。
我没看过你的整个帖子所以我不确定我是否可以提供帮助。 但这解决了我的问题。 我下载了this解决方案。 然后进行了以下更改......
// ...
public partial class ErrorActions:System.Web.UI.Page { private XmlDocument _xmlDocument = new XmlDocument(); public ListBox FromListBox { 得到 { return lstFrom; } }
public ListBox AbortListBox
{
get
{
return lstToAbort;
}
}
public ListBox ClearingListBox
{
get
{
return lstToClearing;
}
}
protected void Page_Load(object sender, EventArgs e)
{
Page.ClientScript.RegisterClientScriptInclude("listboxjs", "/JavaScripts/listbox.js");
if (!IsPostBack)
{
string movejs = "move('{0}','{1}','{2}')";
string unselectjs = "unselect('{0}')";
lstFrom.Attributes["onclick"] = String.Format(unselectjs, lstToAbort.ClientID);
lstFrom.Attributes["onclick"] = String.Format(unselectjs, lstToClearing.ClientID);
lstToAbort.Attributes["onclick"] = String.Format(unselectjs, lstFrom.ClientID);
lstToAbort.Attributes["onclick"] = String.Format(unselectjs, lstToClearing.ClientID);
lstToClearing.Attributes["onclick"] = String.Format(unselectjs, lstFrom.ClientID);
lstToClearing.Attributes["onclick"] = String.Format(unselectjs, lstToAbort.ClientID);
btnToAbort.Attributes["onclick"] = String.Format(movejs, lstFrom.ClientID, lstToAbort.ClientID, hdnDropdownsAbort.ClientID);
btnFromAbort.Attributes["onclick"] = String.Format(movejs, lstToAbort.ClientID, lstFrom.ClientID, hdnDropdownsAbort.ClientID);
btnToClearing.Attributes["onclick"] = String.Format(movejs, lstFrom.ClientID, lstToClearing.ClientID, hdnDropdownsClearing.ClientID);
btnFromClearing.Attributes["onclick"] = String.Format(movejs, lstToClearing.ClientID, lstFrom.ClientID, hdnDropdownsClearing.ClientID);
}
else
{
//if (!(String.IsNullOrEmpty(hdnDropdowns.Value)))
//{
// PopulateListBoxes();
//}
if (!(String.IsNullOrEmpty(hdnDropdownsAbort.Value)))
{
PopulateAbortListBox();
}
if (!(String.IsNullOrEmpty(hdnDropdownsClearing.Value)))
{
PopulateClearingListBox();
}
}
}
private void PopulateListBox(ListBox listBox)
{
listBox.Items.Clear();
XmlNodeList nodes = _xmlDocument.SelectNodes("listboxes/" + listBox.ClientID + "/option");
foreach (XmlNode node in nodes)
{
listBox.Items.Add(new ListItem(node["key"].InnerText, node["value"].InnerText));
}
}
//private void PopulateListBoxes()
//{
// _xmlDocument.LoadXml(HttpUtility.UrlDecode(hdnDropdownsAbort.Value));
// //PopulateListBox(lstFrom);
// PopulateListBox(lstToAbort);
// PopulateListBox(lstToClearing);
//}
private void PopulateAbortListBox()
{
_xmlDocument.LoadXml(HttpUtility.UrlDecode(hdnDropdownsAbort.Value));
PopulateListBox(lstToAbort);
}
private void PopulateClearingListBox()
{
_xmlDocument.LoadXml(HttpUtility.UrlDecode(hdnDropdownsClearing.Value));
PopulateListBox(lstToClearing);
}
protected void btnDoIt_Click(object sender, EventArgs e)
{
MissionErrorCodeDB db = new MissionErrorCodeDB();
db.DeleteErrorCodeActions(ErrorAction.AbortMission);
db.DeleteErrorCodeActions(ErrorAction.GoToClearingStation);
foreach (ListItem item in lstToAbort.Items)
{
db.AddErrorCodeAction(Convert.ToInt32(item.Value), ErrorAction.AbortMission);
}
foreach (ListItem item in lstToClearing.Items)
{
db.AddErrorCodeAction(Convert.ToInt32(item.Value), ErrorAction.GoToClearingStation);
}
}
protected override void OnPreRender(EventArgs e)
{
MissionErrorCodeDB db = new MissionErrorCodeDB();
List<MissionErrorCode> aborts = db.GetAll(ErrorAction.AbortMission);
List<MissionErrorCode> clearing = db.GetAll(ErrorAction.GoToClearingStation);
List<MissionErrorCode> all = db.GetAll();
all.RemoveAll(delegate(MissionErrorCode mec)
{
foreach (MissionErrorCode item in aborts)
{
if( mec.ErrorCode == item.ErrorCode )
return true;
}
return false;
});
all.RemoveAll(delegate(MissionErrorCode mec)
{
foreach (MissionErrorCode item in clearing)
{
if (mec.ErrorCode == item.ErrorCode)
return true;
}
return false;
});
populateBoxFromDatabase(AbortListBox, aborts);
populateBoxFromDatabase(ClearingListBox, clearing);
populateBoxFromDatabase(FromListBox, all);
base.OnPreRender(e);
}
private void populateBoxFromDatabase(ListBox listBox, List<MissionErrorCode> errorCodes)
{
string text;
int textLength = 46;
listBox.Items.Clear();
foreach (MissionErrorCode item in errorCodes)
{
if (item.ErrorText.Length < textLength)
{
text = item.ErrorCode + " - " + item.ErrorText;
}
else
{
text = item.ErrorCode + " - " + item.ErrorText.Substring(0, textLength - 1) + "...";
}
listBox.Items.Add(new ListItem(text, item.ErrorCode.ToString()));
}
}
}
// ...
答案 1 :(得分:0)
为了避免大量的Javascript,我建议您使用几个Ajax调用来完成工作
使用jQuery,您会看到拨打电话非常简单。
祝你好运。答案 2 :(得分:0)
好吧,似乎没有人愿意为我做我的工作,所以这就是我们最终做的事情。 (它还没有完全完成;当它完成时,我可能只是为了完整性而发布代码。)
我们采取了下载和下载JQuery,特别是JQuery UI“可排序”功能。就像我说的那样,主下拉列表现在是一个伪列表框,即高度受限且ul
的{{1}}。每个项目旁边都有五个单选按钮,用Javascript隐藏。 (也就是说,如果Javascript不可用,用户只会看到带有单选按钮的列表。)当您将项目从主列表拖到(脚本生成的)类别列表中时,会标记相应的单选按钮。还会有一些代码在页面加载时运行,以将已标记的选项从主列表移动到适当的类别(即用于编辑功能)。