Как вы можете клонировать объект WPF?
Вопрос
У кого-нибудь есть хороший пример, как глубоко клонировать объект WPF, сохраняя привязки к данным?
Отмеченный ответ - это первая часть.
Вторая часть заключается в том, что вы должны создать ExpressionConverter и внедрить его в процесс сериализации.Подробная информация об этом находится здесь:
http://www.codeproject.com/KB/WPF/xamlwriterandbinding.aspx?fid=1428301&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2801571
Решение
Самый простой способ, которым я это сделал, - использовать XamlWriter для сохранения объекта WPF в виде строки.Метод Save сериализует объект и все его дочерние элементы в логическом дереве.Теперь вы можете создать новый объект и загрузить его с помощью XamlReader.
бывший:Запишите объект в xaml (допустим, объект был элементом управления Grid).:
string gridXaml = XamlWriter.Save(myGrid);
Загрузите его в новый объект:
StringReader stringReader = new StringReader(gridXaml);
XmlReader xmlReader = XmlReader.Create(stringReader);
Grid newGrid = (Grid)XamlReader.Load(xmlReader);
Другие советы
В .NET 4.0 новый стек сериализации xaml значительно упрощает это.
var sb = new StringBuilder();
var writer = XmlWriter.Create(sb, new XmlWriterSettings
{
Indent = true,
ConformanceLevel = ConformanceLevel.Fragment,
OmitXmlDeclaration = true,
NamespaceHandling = NamespaceHandling.OmitDuplicates,
});
var mgr = new XamlDesignerSerializationManager(writer);
// HERE BE MAGIC!!!
mgr.XamlWriterMode = XamlWriterMode.Expression;
// THERE WERE MAGIC!!!
System.Windows.Markup.XamlWriter.Save(this, mgr);
return sb.ToString();
Здесь есть несколько отличных ответов.Очень полезно.Я пробовал различные подходы к копированию обязательной информации, включая подход, описанный в http://pjlcon.wordpress.com/2011/01/14/change-a-wpf-binding-from-sync-to-async-programatically/ но информация здесь самая лучшая в интернете!
Я создал повторно используемый метод расширения для работы с InvalidOperationException “Привязка не может быть изменена после ее использования”. В моем сценарии я поддерживал некоторый код, который кто-то написал, и после крупного обновления платформы DevExpress DXGrid framework он больше не работал.Следующее отлично решило мою проблему.Часть кода, в которой я возвращаю объект, могла бы быть приятнее, и я пересмотрю это позже.
/// <summary>
/// Extension methods for the WPF Binding class.
/// </summary>
public static class BindingExtensions
{
public static BindingBase CloneViaXamlSerialization(this BindingBase binding)
{
var sb = new StringBuilder();
var writer = XmlWriter.Create(sb, new XmlWriterSettings
{
Indent = true,
ConformanceLevel = ConformanceLevel.Fragment,
OmitXmlDeclaration = true,
NamespaceHandling = NamespaceHandling.OmitDuplicates,
});
var mgr = new XamlDesignerSerializationManager(writer);
// HERE BE MAGIC!!!
mgr.XamlWriterMode = XamlWriterMode.Expression;
// THERE WERE MAGIC!!!
System.Windows.Markup.XamlWriter.Save(binding, mgr);
StringReader stringReader = new StringReader(sb.ToString());
XmlReader xmlReader = XmlReader.Create(stringReader);
object newBinding = (object)XamlReader.Load(xmlReader);
if (newBinding == null)
{
throw new ArgumentNullException("Binding could not be cloned via Xaml Serialization Stack.");
}
if (newBinding is Binding)
{
return (Binding)newBinding;
}
else if (newBinding is MultiBinding)
{
return (MultiBinding)newBinding;
}
else if (newBinding is PriorityBinding)
{
return (PriorityBinding)newBinding;
}
else
{
throw new InvalidOperationException("Binding could not be cast.");
}
}
}
Как насчет:
public static T DeepClone<T>(T from)
{
using (MemoryStream s = new MemoryStream())
{
BinaryFormatter f = new BinaryFormatter();
f.Serialize(s, from);
s.Position = 0;
object clone = f.Deserialize(s);
return (T)clone;
}
}
Конечно, это глубокое клонирование любого объекта, и, возможно, это не самое быстрое решение в городе, но оно требует наименьшего технического обслуживания...:)