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

本文关键字:自定义 保存 WPF 用户 | 更新日期: 2023-09-27 18:28:26

我有一个WPF-xaml模板和与各种控件相关的代码。用户可以四处移动这些控件,从而获得所需的布局。但是,一旦用户重新启动程序,控件就会返回到其原始位置。我如何制作它以便用户可以保存布局?

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

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

  1. 用户更改布局[在Window Closing事件上]后,您可以使用XamlWriter静态类保存XAML文件库更改后的布局。事实上,您序列化了容器控件并将其保存在一个文件中。

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

我放了一个样本(由Matt Searles撰写),在这里:

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