어떻게 WPF 객체를 복제 할 수 있습니까?


Answers

가장 간단한 방법은 XamlWriter를 사용하여 WPF 개체를 문자열로 저장하는 것입니다. Save 메서드는 개체와 논리 트리의 모든 자식을 serialize합니다. 이제 새 개체를 만들고 XamlReader를 사용하여 개체를로드 할 수 있습니다.

예 : 객체를 xaml에 씁니다 (객체가 Grid 컨트롤이라고 가정 해 봅시다).

string gridXaml = XamlWriter.Save(myGrid);

새 객체에로드 :

StringReader stringReader = new StringReader(gridXaml);
XmlReader xmlReader = XmlReader.Create(stringReader);
Grid newGrid = (Grid)XamlReader.Load(xmlReader);
Question

누구나 WPF 객체를 깊이 복제하고 데이터 바인딩을 보존하는 좋은 예가 있습니까?

표시된 대답은 첫 번째 부분입니다.

두 번째 부분은 ExpressionConverter를 만들어 직렬화 프로세스에 삽입해야한다는 것입니다. 자세한 내용은 다음을 참조하십시오.
http://www.codeproject.com/KB/WPF/xamlwriterandbinding.aspx?fid=1428301&df=90&mpp=25&noise=3&sort=Position&view=Quick&select=2801571




어때?

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

물론이 딥 클론 모든 개체, 그리고 그것은 마을에서 가장 빠른 해결책이되지 않을 수도 있지만 최소한의 유지 보수가 ... :)




몇 가지 큰 해답이 있습니다. 매우 도움이됩니다. 나는 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.");
        }
    }
}



.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();