c# - XML vinculante en Silverlight sin clases nominales
linq-to-xml xml-binding (4)
¿Podría hacer algo similar a lo que sugiere Bryant con una consulta que utiliza una clase anónima?
es decir:
var data = from c in xml.Descendants("item")
select new { Forename = c.Attribute("forename").Value,
Surname = c.Attribute("surname").Value };
ItemList.ItemsSource = data
Creo que esto debería funcionar, pero no estoy en un lugar donde pueda probarlo. Si no es así, alguien me dirá por qué porque ahora estoy interesado.
Digamos que tengo una simple porción de XML:
<root>
<item forename="Fred" surname="Flintstone" />
<item forename="Barney" surname="Rubble" />
</root>
Después de buscar este XML en Silverlight, me gustaría vincularlo con XAML de este modo: -
<ListBox x:Name="ItemList" Style="{StaticResource Items}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox Text="{Binding Forename}" />
<TextBox Text="{Binding Surname}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Ahora puedo vincular lo suficiente con LINQ a XML y una clase nominal:
public class Person {
public string Forename {get; set;}
public string Surname {get; set;}
}
¿Se puede hacer sin esta clase?
En otras palabras, el acoplamiento entre el código de Silverlight y el XML de entrada está limitado solo a XAML, el otro código fuente es independiente del conjunto de atributos en el elemento de elemento.
Editar : se sugiere el uso de XSD pero, en última instancia, equivale a lo mismo. XSD-> Clase generada.
Editar : una clase anónima no funciona, Silverlight no puede vincularlos.
Editar : Esto tiene que ser bidireccional, el usuario necesita poder editar los valores y estos valores terminan en el XML. (Se modificó TextBlock original a TextBox en la muestra anterior).
Hasta donde yo sé, Silverlight Binding carece de las propiedades XPath que se encuentran en WPF, por lo que no hay una buena manera de enlazar directamente a XML. Cuando me he encontrado con este problema, he usado xsd.exe contra un esquema para generar mis clases y luego uso la Serialización Xml para completarlas. No es ideal, pero al menos no estoy escribiendo y manteniendo las clases y mapeos yo mismo.
Puedes hacer esto con un IValueConverter. Aquí hay uno simple:
public class XAttributeConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
var xml = value as XElement;
var name = parameter as string;
return xml.Attribute(name).Value;
}
}
Luego, en su Xaml puede hacer referencia al convertidor de tipo y pasar el nombre del atributo como parámetro:
<ListBox x:Name="ItemList">
<ListBox.Resources>
<local:XAttributeConverter x:Name="xcvt" />
</ListBox.Resources>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Converter={StaticResource xcvt}, ConverterParameter=forename}" />
<TextBlock Text="{Binding Converter={StaticResource xcvt}, ConverterParameter=surname}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Esto es cuando se vincula al xml cargado en un XElement:
XElement xml = XElement.Parse("<root><item forename=''Fred'' surname=''Flintstone'' /><item forename=''Barney'' surname=''Rubble'' /></root>");
ItemList.ItemsSource = xml.Descendants("item");
No es una sintaxis de enlace súper elegante, pero funciona y es más fácil que mapear clases.
Consulte Enlace a tipos anónimos en Silverlight para obtener información.