Сериализация TextDecorationCollection в WPF - PullRequest
1 голос
/ 07 апреля 2011

Есть ли какой-либо атрибут сериализации xaml, который я могу указать для свойства зависимости, которое фактически является коллекцией (TextDecorationCollection)?

Я хочу использовать сериализацию для клонирования очень большого и сложного объекта. Вот пример кода, упрощенный:

Существует MyVisualObject, который содержит множество свойств, включая собственный шрифт, который я хочу клонировать

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class Export : Attribute
{
}

public class MyVisualObject : DependencyObject
{
    [Export]
    public CustomFont Font
    {
        get { return (CustomFont)GetValue(FontProperty); }
        set { SetValue(FontProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Font.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty FontProperty =
        DependencyProperty.Register("Font", typeof(CustomFont), typeof(MyVisualObject));

    public MyVisualObject()
    {
        this.Font = new CustomFont();
    }
}

И пользовательский шрифт определяется так:

public class CustomFont : DependencyObject
    {
        public TextDecorationCollection Decorations
        {
            get { return (TextDecorationCollection)GetValue(DecorationsProperty); }
            set { SetValue(DecorationsProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TextDecorations.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty DecorationsProperty =
            DependencyProperty.Register("Decorations", typeof(TextDecorationCollection), typeof(CustomFont), new UIPropertyMetadata(new TextDecorationCollection()));

        public CustomFont()
        {
            this.Decorations = System.Windows.TextDecorations.Underline;
        }
    }

Метод глубокого клонирования:

public static T DeepClone<T>(T from)
        {
            object clone = Activator.CreateInstance(from.GetType());

            Type t = from.GetType();
            System.Reflection.PropertyInfo[] pinf = t.GetProperties();

            foreach (PropertyInfo p in pinf)
            {
                bool serialize = false;

                foreach (object temp in p.GetCustomAttributes(true))
                {
                    if (temp is Export)
                    {
                        serialize = true;
                    }
                }

                if (serialize)
                {
                    string xaml = XamlWriter.Save(p.GetValue(from, null));                        
                    XmlReader rd = XmlReader.Create(new StringReader(xaml));
                    p.SetValue(clone, XamlReader.Load(rd), null);
                }                
            }

            return (T)clone;
        }

Проблема в том, что каждый раз, когда я инициализирую Украшения как Подчеркивание

this.Decorations = System.Windows.TextDecorations.Underline;

процесс клонирования завершается с этой ошибкой: «Добавление значения в коллекцию типа« System.Windows.TextDecorationCollection »вызвало исключение». Номер строки «1» и позиция строки «213».

Насколько я узнал, сериализация, которая является этой частью

string xaml = XamlWriter.Save(p.GetValue(from, null));

возвращает xaml, для которого украшения не установлены как коллекция:

<CustomFont xmlns="clr-namespace:WpfApplication1;assembly=WpfApplication1" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <CustomFont.Decorations>
        <av:TextDecoration Location="Underline" /> 
    </CustomFont.Decorations>
</CustomFont>

Но процесс клонирования будет работать, если xaml будет выглядеть так:

<CustomFont xmlns="clr-namespace:WpfApplication1;assembly=WpfApplication1" xmlns:av="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <CustomFont.Decorations>
        <av:TextDecorationCollection>
            <av:TextDecoration Location="Underline" /> 
        </av:TextDecorationCollection>
    </CustomFont.Decorations>
</CustomFont>

Я нашел обходной путь, что-то с заменой строк:

xaml = xaml.Replace("<CustomFont.Decorations><av:TextDecoration Location=\"Underline\" /></CustomFont.Decorations>", "<CustomFont.Decorations><av:TextDecorationCollection><av:TextDecoration Location=\"Underline\" /></av:TextDecorationCollection></CustomFont.Decorations>");

но я думаю, что это действительно грязно, и я бы оценил его, если бы вы могли предоставить более чистое решение (например, указав атрибут для свойства Decorations)

1 Ответ

0 голосов
/ 14 декабря 2011

Вы пытались применить следующий атрибут к свойству Decorations:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...