Скажем, у меня есть простой фрагмент XML: -
<root>
<item forename = "Fred" surname = "Flintstone" />
<item forename = "Barney" surname = "Rubble" />
</root>
Получив этот XML в Silverlight, я хотел бы связать его с XAML этого типа: -
<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>
Теперь я могу достаточно просто связать с LINQ to XML и номинальным классом: -
public class Person {
public string Forename {get; set;}
public string Surname {get; set;}
}
Можно ли без этого класса?
Другими словами, связь между кодом Silverlight и входным XML ограничивается только XAML, другой исходный код не зависит от набора атрибутов элемента item.
Редактировать: предлагается использовать XSD, но в конечном итоге это то же самое. XSD-> Сгенерированный класс.
Редактировать: анонимный класс не работает, Silverlight не может их связать.
Редактировать: Это должно быть двусторонним способом, пользователь должен иметь возможность редактировать значения, и эти значения попадают в XML. (В примере выше исходный TextBlock заменен на TextBox.)





Насколько мне известно, в Silverlight Binding отсутствуют свойства XPath, найденные в WPF, поэтому нет хорошего способа привязки напрямую к XML. Когда я столкнулся с этой проблемой, я использовал xsd.exe против схемы для создания моих классов, а затем использовал сериализацию Xml для их заполнения. Это не идеально, но, по крайней мере, я сам не пишу и не поддерживаю классы и сопоставления.
Вы можете сделать это с помощью IValueConverter. Вот простой:
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;
}
}
Затем в своем Xaml вы можете ссылаться на преобразователь типов и передавать имя атрибута в качестве параметра:
<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>
Это когда вы привязываетесь к xml, загруженному в XElement:
XElement xml = XElement.Parse("<root><item forename='Fred' surname='Flintstone' /><item forename='Barney' surname='Rubble' /></root>");
ItemList.ItemsSource = xml.Descendants("item");
Не очень элегантный синтаксис привязки, но он работает и проще, чем сопоставление с классами.
Это самое близкое, что у меня есть. Я ценю ваши усилия и прошу прощения за плохой вопрос. Проблема, с которой я столкнулся, заключалась в том, чтобы сделать этот подход двояким. (Мой исходный Q содержал TextBlock, я имел в виду TextBox). Мне нужно, чтобы это можно было редактировать.
Не могли бы вы сделать что-то похожее на то, что предлагает Брайант, с запросом, использующим анонимный класс?
то есть:
var data = from c in xml.Descendants("item")
select new { Forename = c.Attribute("forename").Value,
Surname = c.Attribute("surname").Value };
ItemList.ItemsSource = data
Я думаю, это должно сработать, но я не могу это проверить. Если этого не произойдет, кто-нибудь даст мне знать, почему, потому что теперь мне это интересно.
Хорошо, мне приходит в голову, что в этом должно быть что-то в корне не так, иначе это был бы очевидный ответ. Итак, какая часть этого не работает?
Результатом запроса linq является не список объектов, а {System.Linq.Enumerable.WhereSelectEnumerableIterator <System .Xml.Linq.XElement, <> f__AnonymousType0 <S ystem.Xml.Linq.XAttr ibute, System.Xml.Lin q.XAttribute >>}, который, как мне кажется, не может быть привязан. Попробую несколько настроек, чтобы посмотреть, смогу ли я заставить его работать.
Я также пробовал преобразовать его в список с помощью ToList (), но в любом случае получаю исключение: ((System.MethodAccessException) e.ExceptionObject) .Message с сообщением <> f__AnonymousType0`2.get_Forename ().
Вы не можете привязаться к анонимным типам. Silverlight нужны общедоступные классы, а анонимные типы по своей сути являются внутренними.
Хорошо, я думаю, это имеет смысл. Я не понимал, что Silverlight не может связываться с анонимными типами.
Для получения информации см. Привязка к анонимным типам в Silverlight.
Спасибо за ответ. XSD тоже были самыми близкими мне. Я надеялся на что-то более гибкое.