用户在WPF中保存可自定义的模板

时间:2015-12-30 12:26:08

标签: c# wpf xaml

我有一个WPF xaml模板和相关代码,后面有各种控件。用户可以移动这些控件,以便一个人具有所需的布局。但是,一旦用户重新启动程序,控件将返回其原始位置。如何制作以便用户可以保存布局?

1 个答案:

答案 0 :(得分:1)

您可以保存,重新加载布局(xaml):

  1. 用户更改布局 [on Window Closing event] 后,您可以使用XamlWriter static class保存基于XAML文件库更改的布局。实际上,您序列化容器控件并将其保存在文件中。

  2. 此外,您还需要一些代码 [在InitializeComponent()之后的窗口构造函数中到容器控件[及其控件]的重新加载序列化布局来自档案。

  3. 我放了一个样本(由Matt Searles编写),here

    <StackPanel>
        <WrapPanel x:Name="wrapPanel1" Height="200"></WrapPanel>
        <Button Click="AddButton">Add Button</Button>
        <Button Click="SaveButtons">Save Buttons</Button>
        <Button Click="ReloadButtons">Reload Buttons</Button>   
    </StackPanel>
    

    代码背后:

    /// <summary>
    /// Add a button to wrapPanel1
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void AddButton(object sender, RoutedEventArgs e)
    {
        // Create the Button.
        Button button = new Button();
        button.Height = 50;
        button.Width = 100;
        button.Background = Brushes.AliceBlue;
        button.Content = "Click Me";
    
        wrapPanel1.Children.Add(button);
    }
    
    /// <summary>
    /// Save wrapPanel1 to AA.xaml
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void SaveButtons(object sender, RoutedEventArgs e)
    {
        StringBuilder outstr = new StringBuilder();
    
        XmlWriterSettings settings = new XmlWriterSettings();
        settings.Indent = true;
        settings.OmitXmlDeclaration = true;
        settings.NewLineOnAttributes = true;
    
    
        XamlDesignerSerializationManager dsm = new XamlDesignerSerializationManager(XmlWriter.Create(outstr, settings));
        dsm.XamlWriterMode = XamlWriterMode.Expression;
    
        XamlWriter.Save(wrapPanel1, dsm);
        string savedControls = outstr.ToString();
    
        File.WriteAllText(@"AA.xaml", savedControls);
    }
    
    /// <summary>
    /// Reload the buttons in AA.xaml
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void ReloadButtons(object sender, RoutedEventArgs e)
    {
        StreamReader sR = new StreamReader(@"AA.xaml");
        string text = sR.ReadToEnd();
        sR.Close();
    
        StringReader stringReader = new StringReader(text);
        XmlReader xmlReader = XmlReader.Create(stringReader);
    
        WrapPanel wp = (WrapPanel)System.Windows.Markup.XamlReader.Load(xmlReader);
    
        wrapPanel1.Children.Clear(); // clear the existing children
    
        foreach (FrameworkElement child in wp.Children) // and for each child in the WrapPanel we just loaded (wp)
        {
            wrapPanel1.Children.Add(CloneFrameworkElement(child)); // clone the child and add it to our existing wrap panel
        }           
    }
    
    /// <summary>
    /// Clone a framework element by serializing and deserializing it
    /// </summary>
    /// <param name="originalElement"></param>
    /// <returns></returns>
    FrameworkElement CloneFrameworkElement(FrameworkElement originalElement)
    {
        string elementString = XamlWriter.Save(originalElement);
    
        StringReader stringReader = new StringReader(elementString);
        XmlReader xmlReader = XmlReader.Create(stringReader);
        FrameworkElement clonedElement = (FrameworkElement)XamlReader.Load(xmlReader);
    
        return clonedElement;
    }