[英]C# serialization UIElementCollection
I have some code:我有一些代码:
public static UIElementCollection DeSerializeXAML(string filename)
{
// Load XAML from file. Use 'using' so objects are disposed of properly.
using (System.IO.FileStream fs = System.IO.File.Open(filename, System.IO.FileMode.Open, System.IO.FileAccess.Read))
{
return System.Windows.Markup.XamlReader.Load(fs) as UIElementCollection; //EXCEPTION
}
}
// Serializes any UIElement object to XAML using a given filename.
public static void SerializeToXAML(UIElementCollection elements, string filename)
{
// Use XamlWriter object to serialize element
string strXAML = System.Windows.Markup.XamlWriter.Save(elements);
// Write XAML to file. Use 'using' so objects are disposed of properly.
using (System.IO.FileStream fs = System.IO.File.Create(filename))
{
using (System.IO.StreamWriter streamwriter = new System.IO.StreamWriter(fs))
{
streamwriter.Write(strXAML);
}
}
}
private void btnSave_Click(object sender, RoutedEventArgs e)
{
SaveFileDialog dlg = new SaveFileDialog();
dlg.FileName = "UIElement File"; // Default file name
dlg.DefaultExt = ".xaml"; // Default file extension
dlg.Filter = "Xaml File (.xaml)|*.xaml"; // Filter files by extension
// Show save file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process save file dialog box results
if (result == true)
{
// Save document
string filename = dlg.FileName;
SerializeToXAML(myCanvas.Children, filename);
}
}
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".xaml"; // Default file extension
dlg.Filter = "Xaml File (.xaml)|*.xaml"; // Filter files by extension
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
string filename = dlg.FileName;
UIElementCollection elements = DeSerializeXAML(filename) as UIElementCollection;
// Add all child elements (lines, rectangles etc) to canvas
myCanvas.Children.Clear();
foreach (UIElement el in elements)
{
myCanvas.Children.Add(el);
}
}
}
That works fine with serialization but when you deserialize, an exception is thrown.这适用于序列化,但是当您反序列化时,会引发异常。
Text of exception(translated with google):"You did not find a suitable constructor for the type" System.Windows.Controls.UIElementCollection.异常文本(用谷歌翻译):“您没有找到适合该类型的构造函数”System.Windows.Controls.UIElementCollection。
"You can use the Arguments or FactoryMethod directives to generate this type.": Line number "1" and position in line "22". “您可以使用 Arguments 或 FactoryMethod 指令来生成此类型。”:行号“1”和行“22”中的位置。
A UIElementCollection
instance is tied to a specific Visual
, and as such, it is unsuitable for serialization (as @kostya-k points out). UIElementCollection
实例绑定到特定的Visual
,因此,它不适合序列化(正如@kostya-k 指出的那样)。 The deserialization logic doesn't know how to create a new UIElementCollection
because it doesn't know which Visual
to associate it with.反序列化逻辑不知道如何创建新的UIElementCollection
因为它不知道将它与哪个Visual
关联。 And creating a new collection is pointless anyway, as you are simply transferring the values to myCanvas.Children
.无论如何,创建一个新集合是没有意义的,因为您只是将值转移到myCanvas.Children
。
The good news is that you can use a XamlObjectWriter
to populate myCanvas.Children
directly instead of instantiatating a new collection:好消息是您可以使用XamlObjectWriter
直接填充myCanvas.Children
而不是实例化新集合:
public static void DeSerializeXAML(UIElementCollection elements, string filename)
{
var context = System.Windows.Markup.XamlReader.GetWpfSchemaContext();
var settings = new System.Xaml.XamlObjectWriterSettings
{
RootObjectInstance = elements
};
using (var reader = new System.Xaml.XamlXmlReader(filename))
using (var writer = new System.Xaml.XamlObjectWriter(context, settings))
{
System.Xaml.XamlServices.Transform(reader, writer);
}
}
private void btnLoad_Click(object sender, RoutedEventArgs e)
{
Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();
dlg.DefaultExt = ".xaml"; // Default file extension
dlg.Filter = "Xaml File (.xaml)|*.xaml"; // Filter files by extension
// Show open file dialog box
Nullable<bool> result = dlg.ShowDialog();
// Process open file dialog box results
if (result == true)
{
string filename = dlg.FileName;
myCanvas.Children.Clear();
DeSerializeXAML(myCanvas.Children, filename);
}
}
UIElementCollection
is not intended for serialization. UIElementCollection
不用于序列化。 It meant to be used when building a WPF visual tree.它意味着在构建 WPF 可视化树时使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.