Как вы можете клонировать объект WPF? - PullRequest
37 голосов
/ 28 августа 2008

У кого-нибудь есть хороший пример, как глубоко клонировать объект WPF, сохраняя привязки данных?


Отмеченный ответ - первая часть.

Вторая часть заключается в том, что вы должны создать ExpressionConverter и внедрить его в процесс сериализации. Подробности для этого здесь:
http://www.codeproject.com/KB/WPF/xamlwriterandbinding.aspx?fid=1428301&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2801571

Ответы [ 4 ]

59 голосов
/ 28 августа 2008

Самый простой способ сделать это - использовать 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);
33 голосов
/ 11 февраля 2011

В .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();
4 голосов
/ 07 февраля 2013

Здесь есть несколько отличных ответов. Очень полезно. Я пробовал различные подходы для копирования информации о связывании, включая подход, описанный в http://pjlcon.wordpress.com/2011/01/14/change-a-wpf-binding-from-sync-to-async-programatically/, но информация здесь самая лучшая в Интернете!

Я создал повторно используемый метод расширения для работы с InvalidOperationException «Привязка не может быть изменена после того, как она была использована». В моем сценарии я поддерживал некоторый код, который кто-то написал, и после крупного обновления инфраструктуры DevExpress DXGrid он не дольше работал. Следующее решило мою проблему отлично. Часть кода, в которую я возвращаю объект, могла бы быть лучше, и я переформулирую это позже.

/// <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.");
        }
    }
}
0 голосов
/ 28 августа 2008

Как насчет:

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

Конечно, это глубоко клонирует любой объект, и, возможно, это не самое быстрое решение в городе, но оно требует минимального обслуживания ...

...