valor seleccionar por poner net llenar item ejemplos dropdownlist1 dropdownlist desde defecto datos cargar asp asp.net drop-down-menu postback behavior listitem

asp.net - seleccionar - Los atributos ListItems en una DropDownList se pierden en la devolución de datos?



poner un valor por defecto en un dropdownlist asp net (11)

@Sujay Podría agregar un texto separado por punto y coma en el atributo de valor de la lista desplegable (como el estilo csv) y usar String.Split ('';'') para obtener 2 "valores" del único valor, como una solución para alejarse sin tener que crear un nuevo control de usuario. Especialmente si solo tiene algunos atributos adicionales, y si no es demasiado largo. También puede usar un valor JSON en el atributo de valor de la lista desplegable y luego analizar todo lo que necesite desde allí.

Un compañero de trabajo me mostró esto:

Él tiene una DropDownList y un botón en una página web. Aquí está el código detrás:

protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { ListItem item = new ListItem("1"); item.Attributes.Add("title", "A"); ListItem item2 = new ListItem("2"); item2.Attributes.Add("title", "B"); DropDownList1.Items.AddRange(new[] {item, item2}); string s = DropDownList1.Items[0].Attributes["title"]; } } protected void Button1_Click(object sender, EventArgs e) { DropDownList1.Visible = !DropDownList1.Visible; }

En la carga de la página, se muestran los consejos sobre herramientas de los elementos, pero en la primera devolución se pierden los atributos. ¿Por qué es este el caso, y hay soluciones temporales?


Aquí está el código VB.Net de la solución propuesta por Laramie y refinado por gleapman.

Actualización: el código que publiqué a continuación es en realidad para el control ListBox. Simplemente cambie la herencia a DropDownList y cambie el nombre de la clase.

Imports System.Collections.Generic Imports System.ComponentModel Imports System.Security.Permissions Imports System.Linq Imports System.Text Imports System.Web Imports System.Web.UI Imports System.Web.UI.WebControls Namespace CustomControls <DefaultProperty("Text")> _ <ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")> Public Class PersistentListBox Inherits ListBox <Bindable(True)> _ <Category("Appearance")> _ <DefaultValue("")> _ <Localizable(True)> _ Protected Overrides Function SaveViewState() As Object '' Create object array for Item count + 1 Dim allStates As Object() = New Object(Me.Items.Count + 1) {} '' The +1 is to hold the base info Dim baseState As Object = MyBase.SaveViewState() allStates(0) = baseState Dim i As Int32 = 1 '' Now loop through and save each attribute for the List For Each li As ListItem In Me.Items Dim j As Int32 = 0 Dim attributes As String()() = New String(li.Attributes.Count - 1)() {} For Each attribute As String In li.Attributes.Keys attributes(j) = New String() {attribute, li.Attributes(attribute)} j += 1 Next allStates(i) = attributes i += 1 Next Return allStates End Function Protected Overrides Sub LoadViewState(savedState As Object) If savedState IsNot Nothing Then Dim myState As Object() = DirectCast(savedState, Object()) '' Restore base first If myState(0) IsNot Nothing Then MyBase.LoadViewState(myState(0)) End If Dim i As Int32 = 1 For Each li As ListItem In Me.Items '' Loop through and restore each attribute '' NOTE: Ignore the first item as that is the base state and is represented by a Triplet struct For Each attribute As String() In DirectCast(myState(i), String()()) li.Attributes(attribute(0)) = attribute(1) i += 1 Next Next End If End Sub End Class End Namespace


Gracias, Laramie. Justo lo que estaba buscando. Mantiene los atributos perfectamente.

Para expandir, a continuación se muestra un archivo de clase que creé usando el código de Laramie para crear una lista desplegable en VS2008. Crea la clase en la carpeta App_Code. Después de crear la clase, use esta línea en la página aspx para registrarla:

<%@ Register TagPrefix="aspNewControls" Namespace="NewControls"%>

A continuación, puede poner el control en su formulario web con este

<aspNewControls:NewDropDownList ID="ddlWhatever" runat="server"> </aspNewControls:NewDropDownList>

Ok, esta es la clase ...

using System; using System.Collections.Generic; using System.ComponentModel; using System.Security.Permissions; using System.Linq; using System.Text; using System.Web; using System.Web.UI; using System.Web.UI.WebControls; namespace NewControls { [DefaultProperty("Text")] [ToolboxData("<{0}:ServerControl1 runat=server></{0}:ServerControl1>")] public class NewDropDownList : DropDownList { [Bindable(true)] [Category("Appearance")] [DefaultValue("")] [Localizable(true)] protected override object SaveViewState() { // create object array for Item count + 1 object[] allStates = new object[this.Items.Count + 1]; // the +1 is to hold the base info object baseState = base.SaveViewState(); allStates[0] = baseState; Int32 i = 1; // now loop through and save each Style attribute for the List foreach (ListItem li in this.Items) { Int32 j = 0; string[][] attributes = new string[li.Attributes.Count][]; foreach (string attribute in li.Attributes.Keys) { attributes[j++] = new string[] { attribute, li.Attributes[attribute] }; } allStates[i++] = attributes; } return allStates; } protected override void LoadViewState(object savedState) { if (savedState != null) { object[] myState = (object[])savedState; // restore base first if (myState[0] != null) base.LoadViewState(myState[0]); Int32 i = 1; foreach (ListItem li in this.Items) { // loop through and restore each style attribute foreach (string[] attribute in (string[][])myState[i++]) { li.Attributes[attribute[0]] = attribute[1]; } } } } } }


La solución simple es agregar los atributos de información sobre herramientas en el evento de pre-render del menú desplegable. Cualquier cambio en el estado debe hacerse en el evento de pre-render .

Código de muestra :

protected void drpBrand_PreRender(object sender, EventArgs e) { foreach (ListItem _listItem in drpBrand.Items) { _listItem.Attributes.Add("title", _listItem.Text); } drpBrand.Attributes.Add("onmouseover", "this.title=this.options[this.selectedIndex].title"); }


Las soluciones típicas a este problema implican la creación de nuevos controles que no son del todo factibles en circunstancias normales. Hay una solución simple pero trivial a este problema.

El problema es que ListItem pierde sus atributos en la devolución de datos. Sin embargo, la Lista en sí nunca pierde ningún atributo personalizado. Uno puede aprovechar esto de una manera simple pero efectiva de esta manera.

Pasos:

  1. Serialice sus atributos usando el código en la respuesta anterior ( https://.com/a/3099755/3624833 )

  2. Guárdelo en un atributo personalizado de ListControl (lista desplegable, checklistbox, lo que sea).

  3. En la publicación posterior, vuelva a leer el atributo personalizado de ListControl y deserialícelo de nuevo como atributos.

Aquí está el código que solía (de) serializar atributos (Lo que tenía que hacer era hacer un seguimiento de los elementos de la lista que originalmente se mostraban como seleccionados cuando se recuperaban del backend y luego guardar o eliminar filas según los cambios realizados por el usuario en la interfaz de usuario):

string[] selections = new string[Users.Items.Count]; for(int i = 0; i < Users.Items.Count; i++) { selections[i] = string.Format("{0};{1}", Users.Items[i].Value, Users.Items[i].Selected); } Users.Attributes["data-item-previous-states"] = string.Join("|", selections);

(arriba, "Usuarios" es un control CheckboxList ).

En la publicación posterior (en mi caso, un evento Enviar clic), utilizo el siguiente código para recuperar el mismo y almacenarlo en un diccionario para el procesamiento posterior:

Dictionary<Guid, bool> previousStates = new Dictionary<Guid, bool>(); string[] state = Users.Attributes["data-item-previous-states"].Split(new char[] {''|''}, StringSplitOptions.RemoveEmptyEntries); foreach(string obj in state) { string[] kv = obj.Split(new char[] { '';'' }, StringSplitOptions.None); previousStates.Add(kv[0], kv[1]); }

(PD: Tengo un funcs de biblioteca que realiza el manejo de errores y las conversiones de datos, omitiendo el mismo aquí para abreviar).


Me las arreglé para lograr eso usando Session Variables, en mi caso mi lista no va a contener muchos elementos por lo que funciona bastante bien, así es como lo hice:

protected void Page_Load(object sender, EventArgs e) { if (!IsPostBack) { string[] elems;//Array with values to add to the list for (int q = 0; q < elems.Length; q++) { ListItem li = new ListItem() { Value = "text", Text = "text" }; li.Attributes["data-image"] = elems[q]; myList.Items.Add(li); HttpContext.Current.Session.Add("attr" + q, elems[q]); } } else { for (int o = 0; o < webmenu.Items.Count; o++) { myList.Items[o].Attributes["data-image"] = HttpContext.Current.Session["attr" + o].ToString(); } } }

Cuando la página se carga la primera vez que se completa la lista y agrego un atributo de imagen que se pierde después de la devolución de datos :( entonces, cuando agrego los elementos con sus atributos, creo una variable de sesión "attr" más el número del elemento tomado del ciclo "para" (será como attr0, attr1, attr2, etc ...) y en ellos guardo el valor del atributo (una ruta a una imagen en mi caso), cuando se produce la devolución (dentro del " else ") Solo hago un bucle en la lista y agrego el atributo tomado de la variable Session usando el" int "del bucle" for "que es el mismo que cuando se cargó la página (esto es porque en esta página no agrego elementos a la lista simplemente seleccionando para que siempre tengan el mismo índice) y los atributos se establecen nuevamente, espero que esto ayude a alguien en el futuro, ¡saludos!


Si solo desea cargar los elementos de lista en la primera carga de la página, deberá habilitar ViewState para que el control pueda serializar su estado allí y volver a cargarlo cuando la página se publique.

Hay varios lugares donde se puede habilitar ViewState: verifique el nodo <pages/> en web.config y también en la directiva <%@ page %> en la parte superior del archivo aspx para la propiedad EnableViewState . Esta configuración deberá ser true para que ViewState funcione.

Si no desea usar ViewState, simplemente elimine if (!IsPostBack) { ... } del código que agrega los ListItems y los elementos se recrearán en cada devolución.

Editar: me disculpo, leí mal su pregunta. Tiene razón en que los atributos no sobreviven a la devolución, ya que no están serializados en ViewState. Debe volver a agregar esos atributos en cada devolución.


Solución simple sin ViewState, creando nuevo control de servidor o complejo smth:

Creando:

public void AddItemList(DropDownList list, string text, string value, string group = null, string type = null) { var item = new ListItem(text, value); if (!string.IsNullOrEmpty(group)) { if (string.IsNullOrEmpty(type)) type = "group"; item.Attributes["data-" + type] = group; } list.Items.Add(item); }

Actualización:

public void ChangeItemList(DropDownList list, string eq, string group = null, string type = null) { var listItem = list.Items.Cast<ListItem>().First(item => item.Value == eq); if (!string.IsNullOrEmpty(group)) { if (string.IsNullOrEmpty(type)) type = "group"; listItem.Attributes["data-" + type] = group; } }

Ejemplo:

protected void Page_Load(object sender, EventArgs e) { if (!Page.IsPostBack) { using (var context = new WOContext()) { context.Report_Types.ToList().ForEach(types => AddItemList(DropDownList1, types.Name, types.ID.ToString(), types.ReportBaseTypes.Name)); DropDownList1.DataBind(); } } else { using (var context = new WOContext()) { context.Report_Types.ToList().ForEach(types => ChangeItemList(DropDownList1, types.ID.ToString(), types.ReportBaseTypes.Name)); } } }


Tuve el mismo problema y quería contribuir con this recurso en el que el autor creaba un elemento heredado ListItem Consumer para conservar los atributos en ViewState. Con suerte, salvará a alguien el tiempo que desperdicié hasta que tropecé con él.

protected override object SaveViewState() { // create object array for Item count + 1 object[] allStates = new object[this.Items.Count + 1]; // the +1 is to hold the base info object baseState = base.SaveViewState(); allStates[0] = baseState; Int32 i = 1; // now loop through and save each Style attribute for the List foreach (ListItem li in this.Items) { Int32 j = 0; string[][] attributes = new string[li.Attributes.Count][]; foreach (string attribute in li.Attributes.Keys) { attributes[j++] = new string[] {attribute, li.Attributes[attribute]}; } allStates[i++] = attributes; } return allStates; } protected override void LoadViewState(object savedState) { if (savedState != null) { object[] myState = (object[])savedState; // restore base first if (myState[0] != null) base.LoadViewState(myState[0]); Int32 i = 1; foreach (ListItem li in this.Items) { // loop through and restore each style attribute foreach (string[] attribute in (string[][])myState[i++]) { li.Attributes[attribute[0]] = attribute[1]; } } } }


Una solución simple: llame a la función de carga desplegable en el evento de clic donde solicita la devolución de la publicación.


//In the same block where the ddl is loaded (assuming the dataview is retrieved whether postback or not), search for the listitem and re-apply the attribute if(IsPostBack) foreach (DataRow dr in dvFacility.Table.Rows) { //search the listitem ListItem li = ddl_FacilityFilter.Items.FindByValue(dr["FACILITY_CD"].ToString()); if (li!=null) { li.Attributes.Add("Title", dr["Facility_Description"].ToString()); } } //end for each