Graeme_Grant
Следующее облегчит доступ к данным...
Класс данных:
[XmlRoot(ElementName="billingdetails")]
public class Billingdetails {
[XmlElement(ElementName="customername")]
public string Customername { get; set; }
[XmlElement(ElementName="address")]
public string Address { get; set; }
[XmlElement(ElementName="psid")]
public string Psid { get; set; }
[XmlElement(ElementName="state")]
public string State { get; set; }
}
[XmlRoot(ElementName="shippingdetails")]
public class Shippingdetails {
[XmlElement(ElementName="name")]
public string Name { get; set; }
[XmlElement(ElementName="address")]
public string Address { get; set; }
[XmlElement(ElementName="state")]
public string State { get; set; }
}
[XmlRoot(ElementName="Customer")]
public class Customer {
[XmlElement(ElementName="billingdetails")]
public Billingdetails Billingdetails { get; set; }
[XmlElement(ElementName="shippingdetails")]
public Shippingdetails Shippingdetails { get; set; }
[XmlAttribute(AttributeName="ID")]
public string ID { get; set; }
}
[XmlRoot(ElementName="customers")]
public class Customers {
[XmlElement(ElementName="Customer")]
public List<Customer> Customer { get; set; }
}
Обычай
XmlSerializerFactoryNoThrow
:
// ref: http://stackoverflow.com/questions/1127431/xmlserializer-giving-filenotfoundexception-at-constructor/39642834#39642834
public static class XmlSerializerFactoryNoThrow
{
public static Dictionary<Type, XmlSerializer> cache = new Dictionary<Type, XmlSerializer>();
private static object SyncRootCache = new object();
public static XmlSerializer Create(Type type)
{
XmlSerializer serializer;
lock (SyncRootCache)
if (cache.TryGetValue(type, out serializer))
return serializer;
lock (type) //multiple variable of type of one type is same instance
{
//constructor XmlSerializer.FromTypes does not throw the first chance exception
serializer = XmlSerializer.FromTypes(new[] { type })[0];
//serializer = XmlSerializerFactoryNoThrow.Create(type);
}
lock (SyncRootCache) cache[type] = serializer;
return serializer;
}
}
Основной XML-помощник
public static class XmlConverter
{
public static string FromClass<T>(T data, XmlSerializerNamespaces ns = null)
{
string response = string.Empty;
MemoryStream ms = new MemoryStream();
try
{
ms = FromClassToStream(data, ns);
if (ms != null)
{
ms.Position = 0;
using (StreamReader sr = new StreamReader(ms))
response = sr.ReadToEnd();
}
}
finally
{
// don't want memory leaks...
ms.Flush();
ms.Dispose();
ms = null;
}
return response;
}
public static MemoryStream FromClassToStream<T>(T data, XmlSerializerNamespaces ns = null)
{
MemoryStream stream = default(MemoryStream);
if (data != null)
{
XmlWriterSettings settings = new XmlWriterSettings()
{
Encoding = Encoding.UTF8,
Indent = true,
ConformanceLevel = ConformanceLevel.Auto,
CheckCharacters = true,
OmitXmlDeclaration = false
};
//XmlSerializer ser = new XmlSerializer(typeof(T));
XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(T));
stream = new MemoryStream();
using (XmlWriter writer = XmlWriter.Create(stream, settings))
{
serializer.Serialize(writer, data, ns);
writer.Flush();
}
stream.Position = 0;
}
return stream;
}
public static T ToClass<T>(string data)
{
T response = default(T);
if (!string.IsNullOrEmpty(data))
{
XmlReaderSettings settings = new XmlReaderSettings() { IgnoreWhitespace = true };
//XmlSerializer ser = new XmlSerializer(typeof(T));
XmlSerializer serializer = XmlSerializerFactoryNoThrow.Create(typeof(T));
XmlReader reader = XmlReader.Create(new StringReader(data), settings);
response = (T) Convert.ChangeType(serializer.Deserialize(reader), typeof(T));
}
return response;
}
}
Использовать:
var rawXml = IO.File.ReadAllText(fileName);
var customers = XmlConverter.ToClass<Customers>(rawXml);
BindList(comboBox1, customers.Customer, "ID", "ID");
И привязки и методы выбора со списком пользователей :
public void BindList<TModel>(ListControl ctrl, IList<TModel> dataSource, string displayMember, string valueMember)
{
isBusy = true;
ctrl.DisplayMember = displayMember;
ctrl.ValueMember = valueMember;
ctrl.DataSource = dataSource;
isBusy = false;
}
private bool isBusy;
private void comboBox1_SelectedValueChanged(object sender, EventArgs e)
{
if (isBusy) return;
// User has made a selection
var selected = comboBox1.SelectedItem;
Debugger.Break();
}
BillWoodruff
любопытно: разве вызов 'BindList не требует универсального спецификатора типа: BindList(comboBox1, customers.Поддержки, "идентификатор", "идентификатор");
Graeme_Grant
Тип выводится с помощью customers.Customer
который List<Customer>
.. компилятор выполняет работу по преобразованию его в BindList<Customer>(comboBox1, customers.Customer, "ID", "ID");
BillWoodruff
Без объяснения того, что здесь делает "TMmodel", я не могу понять смысла этого кода ... но это не значит, что ОП не может :)
BillWoodruff
-Вы знакомы с дженериками?" да ! и именно поэтому я спрашиваю вас, почему вызов BindingList не имеет определенного универсального типа и что такое TModel.
Я действительно понимаю, что класс, содержащийся в универсальном классе, "наследует" универсальность содержащего класса ... это единственный известный мне случай, когда общие спецификаторы могут быть опущены. Но здесь я этого не вижу.