我有一个WPF xaml模板和相关代码,后面有各种控件。用户可以移动这些控件,以便一个人具有所需的布局。但是,一旦用户重新启动程序,控件将返回其原始位置。如何制作以便用户可以保存布局?
答案 0 :(得分:1)
您可以保存,重新加载布局(xaml
):
用户更改布局 [on Window Closing
event] 后,您可以使用XamlWriter
static class保存基于XAML文件库更改的布局。实际上,您序列化容器控件并将其保存在文件中。
此外,您还需要一些代码 [在InitializeComponent()
之后的窗口构造函数中到容器控件[及其控件]的重新加载序列化布局来自档案。
我放了一个样本(由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;
}