[英]Serializing a class containing a WPF Brush using `DataContractSerializer`
I have a class that I am serializing like: 我有一个要序列化的类,例如:
using (FileStream fileStreamWriter = new FileStream(fileName, FileMode.Create))
{
var dataContractSerializer = new DataContractSerializer(typeof(ClassToBeSerialized));
dataContractSerializer.WriteObject(fileStreamWriter, btChartGroupList);
fileStreamWriter.Close();
}
This works fine until I add a property of type Brush
(called AreaBrush
) to the ClassToBeSerialized
class. 直到我将类型Brush
的属性(称为AreaBrush
)添加到ClassToBeSerialized
类,该方法ClassToBeSerialized
。 This AreaBrush
property could be a SolidBrush
, LinearGradientBrush
or a RadialGradientBrush
. 这AreaBrush
属性可能是一个SolidBrush
, LinearGradientBrush
或RadialGradientBrush
。 During serialization, DataContractSerializer
throws: 序列化期间, DataContractSerializer
引发:
Type 'System.Windows.Media.MatrixTransform' with data contract name 'MatrixTransform: http://schemas.datacontract.org/2004/07/System.Windows.Media ' is not expected. 键入数据合同名称为MatrixTransform的“ System.Windows.Media.MatrixTransform”:不应为http://schemas.datacontract.org/2004/07/System.Windows.Media 。 Consider using a DataContractResolver if you are using DataContractSerializer or add any types not known statically to the list of known types - for example, by using the KnownTypeAttribute attribute or by adding them to the list of known types passed to the serializer. 如果您正在使用DataContractSerializer或将任何不是静态已知的类型添加到已知类型的列表中,请考虑使用DataContractResolver-例如,通过使用KnownTypeAttribute属性或将它们添加到传递给序列化程序的已知类型的列表中。
Any ideas on how I can get this to work? 关于如何使它起作用的任何想法? I played around with the BrushConverter
but didn't have much luck with that. 我玩过BrushConverter
但运气不佳。
I guess I could add all 3 types of brushes as properties but I am hoping for a better solution. 我想我可以将所有3种类型的笔刷都添加为属性,但是我希望有一个更好的解决方案。
EDIT: With the help of VMaleev I ended up doing this: 编辑:在VMaleev的帮助下,我最终做到了:
[IgnoreDataMember]
public Brush AreaBrush
{
get { return _areaBrush; }
set
{
SetProperty(ref _areaBrush, value, () => AreaBrush);
}
}
[DataMember]
public string AreaBrushText
{
get
{
using (StringWriter sw = new StringWriter())
{
XamlWriter.Save(AreaBrush, sw);
string s = sw.ToString();
return sw.ToString();
}
}
set
{
AreaBrush = (Brush)XamlReader.Parse(value);
}
}
You cannot do that simply. 您不能简单地做到这一点。 I would recommend you to mark your Brush property as [XmlIgnore] and serialize and deserialize it separately using XamlWriter and XamlReader : 我建议您将Brush属性标记为[XmlIgnore],并分别使用XamlWriter和XamlReader对其进行序列化和反序列化:
// example of writing
using (var outfile = File.CreateText("Brush.xaml"))
{
XamlWriter.Save(brush, outfile);
}
// example of reading
using (Stream s = File.OpenRead("Brush.xaml"))
{
Brush b = XamlReader.Load(s);
}
You can serialize an arbitrary WPF element by wrapping it in a class which implements IXmlSerializable
: 您可以通过将任意WPF元素包装在实现IXmlSerializable
的类中来序列化:
[DataContract]
class ClassToBeSerialized
{
public LinearGradientBrush Brush { get; set; }
[DataMember(Name = "Brush")]
private XamlSerializationWrapper<LinearGradientBrush> BrushSerializer
{
get { return new XamlSerializationWrapper<LinearGradientBrush>(Brush); }
set { Brush = value.Element; }
}
}
class XamlSerializationWrapper<TElement> : IXmlSerializable
{
public TElement Element { get; private set; }
protected XamlSerializationWrapper()
{
}
public XamlSerializationWrapper(TElement element)
{
this.Element = element;
}
public System.Xml.Schema.XmlSchema GetSchema()
{
return null;
}
public void ReadXml(XmlReader reader)
{
// this is a bit circuitous, but XamlReader.Load closes the reader for some reason
var element = (XElement)XElement.ReadFrom(reader);
Element = (TElement)XamlReader.Parse(element.Elements().Single().ToString());
}
public void WriteXml(XmlWriter writer)
{
XamlWriter.Save(Element, writer);
}
}
Example XML: XML示例:
<?xml version="1.0" encoding="utf-16"?>
<ClassToBeSerialized xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/WpfSerialization">
<Brush>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<LinearGradientBrush.GradientStops>
<GradientStop Color="#FF000000" Offset="0" />
<GradientStop Color="#FFFFFFFF" Offset="1" />
</LinearGradientBrush.GradientStops>
</LinearGradientBrush>
</Brush>
</ClassToBeSerialized>
Example use: 使用示例:
public static string ToXml(ClassToBeSerialized cts)
{
var dcs = new DataContractSerializer(typeof(ClassToBeSerialized));
using (var sb = new StringWriter())
{
using (var xs = XmlWriter.Create(sb, new XmlWriterSettings() { Indent = true }))
{
dcs.WriteObject(xs, cts);
}
return sb.ToString();
}
}
public static ClassToBeSerialized FromXml(string xml)
{
var dcs = new DataContractSerializer(typeof(ClassToBeSerialized));
return (ClassToBeSerialized)dcs.ReadObject(XmlReader.Create(new StringReader(xml)));
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.