简体   繁体   English

C# 序列化 UIElementCollection

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM