C#serialization UIElementCollection

时间:2017-10-02 14:10:24

标签: c# xaml serialization deserialization

我有一些代码:

    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);
            }
        }
    }

这对序列化工作正常,但是当你反序列化时,会引发异常。

  

异常文本(使用谷歌翻译):“您没有为类型”System.Windows.Controls.UIElementCollection找到合适的构造函数。

     

“您可以使用Arguments或FactoryMethod指令生成此类型。”:行号“1”和位置“22”。

2 个答案:

答案 0 :(得分:1)

UIElementCollection实例与特定的Visual绑定,因此,它不适合序列化(如@ kostya-k指出)。反序列化逻辑不知道如何创建新的UIElementCollection,因为它不知道将Visual与哪个myCanvas.Children相关联。无论如何,创建新集合毫无意义,因为您只是将值传递给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); } } ,而不是实例化新的集合:

$(document).ready(function() {
  $("#button").click(function() {
    var e = jQuery.Event("keydown");
    e.keyCode = 37;
    $(this).trigger(e);
    console.log(e);
    return false;
  });
});

// test trigger
$(window).keydown(function(e) {
  key = e.keyCode ? e.keyCode : e.which;
  if (key === 37) {
    alert(`Left arrow triggered, (keyCode ${key})`);
  }
});

答案 1 :(得分:0)

UIElementCollection不适用于序列化。它意味着在构建WPF可视化树时使用。