ListView DataItem muestra nulo
Pregunta
Hace unos días, yo escribió sobre problemas con la implementación de un ListView en ASP.NET.Ahora, con todo el resto del código escrito, tengo problemas para guardar los elementos modificados en ListView.
Algunas cosas a tener en cuenta:
- El botón Guardar no forma parte del ListView propiamente dicho;llama al
GetListViewItems()
método, que a su vez llama alSave()
método. - El
Listview.DataBind()
El evento se invoca cuando se presiona un botón solicitando que se actualicen los registros. - La vista de lista muestra texto usando
<%#Eval("Key.Name") %>
y un llamadoDropDownList
usando<%#Eval("Value") %>
Obtener los elementos de ListView
public void GetListViewItems()
{
List<Foo> Result = FooManager.CreateFooList();
DropDownList ddl = null;
ListViewItem Item = null;
try
{
foreach (ListViewDataItem item in lvFooList.Items)
{
Item = item;
ddl = ((DropDownList) (Item.FindControl("ddlListOfBars")));
if (//something is there)
{
Foo foo = FooManager.CreateFoo();
foo.Id = item.DataItemIndex; //shows null
int barId = int.Parse(ddl.SelectedItem.Value); //works just fine
foo.barId = barId;
Result.Add(foo);
}
}
}
catch (Exception ex)
{
//Irrelevant for our purposes
}
}
Enlace de datos al ListView
El código para vincular datos de ListView es se muestra aquí en mi pregunta anterior.
Preguntas):
- ¿Por qué cuando repito el
ListViewDataItem
en elListview
que cada elemento esnull
? - ¿Cómo puedo recuperar el
Foo.Id
del Diccionario? - ¿Qué más podría faltarme?
- ¿Qué usaría si quisiera conseguir eso?
Id
¿Programáticamente en función de los elementos que se mostraron?Tal como está ahora, el ListView actual se muestra en función de lo queFoo
s fueron seleccionados.AquellosFoo
Luego se muestran los elementos seleccionados y el usuario puede cambiar losBar
en elDropDownList
, presione Guardar y esos cambios se propagarán.
Actualizar
Resulta que mi problema era qué leppi había dicho;y eso era lo que necesitaba especificar DataKeyNames
y utilícelos para conservar la información de ListView.
Aquí está el código que agregué:
try
{
int DataKeyArrayIndex = 0;
foreach (ListViewDataItem item in lvFooList.Items)
{
Item = item;
ddl = ((DropDownList) (Item.FindControl("ddlListOfBars")));
if (//something is there)
{
Foo foo = FooManager.CreateFoo();
Foo tempFoo = FooManager.CreateFoo();
if (lvFooList != null)
{
tempFoo = ((Foo)(lvFooList.DataKeys[DataKeyArrayIndex].Value));
}
foo.Id = tempFoo.Id;
int barId = int.Parse(ddl.SelectedItem.Value); //works just fine
foo.barId = barId;
Result.Add(foo);
DataKeyArrayIndex++;
}
}
}
Y luego en el .ascx
archivo, agregué DataKeyNames="Key"
, al igual que:
<asp:ListView ID="lvFooList" runat="server" DataKeyNames="Key">
Esto me permitió utilizar el Key
de mi publicación anterior para determinar qué Foo estaba siendo observado.
Cualquier crítica a este enfoque, así como los métodos para mejorarlo, serán muy apreciadas.
Solución
Algunas respuestas rápidas:
Su necesidad de utilizar el enlace de datos para que eso funcione, en otras palabras, asignar a
DataSource
y llamaDataBind()
.EDITAR:Parece que estás haciendo eso.Pero recuerde que no persistirá entre devoluciones de datos, solo elDataKey
(vea abajo).Si no recuerdo mal, es necesario especificar el
DataKeyNames
, y se pueden recuperar desde elDataKey
propiedad entonces.
Otros consejos
también puede usar la propiedad ListViewDataItem.DataItemIndex en lugar de mantener su propio índice, como en:
foreach (ListViewDataItem item in MyListView.Items)
{
// in this example key is a string value
Foo foo = new Foo(MyListView.DataKeys[item.DataItemIndex].Value as string);
// do stuff with foo
}