2011-04-07 6 views
0

Existe-t-il un attribut de sérialisation xaml que je puisse spécifier pour une propriété de dépendance qui est en fait une collection (TextDecorationCollection)?Sérialisation TextDecorationCollection dans WPF

Je souhaite utiliser la sérialisation pour cloner un objet très volumineux et complexe. Voici un échantillon du code, simplifié:

Il y a un MyVisualObject, qui contient beaucoup de propriétés, y compris une police personnalisée, que je veux cloner

[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(); 
    } 
} 

Et la police personnalisée est définie comme celui-ci :

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

la méthode clone profonde:

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

Le problème i s que chaque fois que j'initialiser les décorations comme Souligné

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

le processus de clonage se bloque avec cette erreur: « Ajouter de la valeur de collection de type « System.Windows.TextDecorationCollection » a généré une exception. » Numéro de ligne '1' et position de ligne '213'.

Pour autant que j'ai découvert, la sérialisation, qui est cette partie

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

retourne un XAML qui ne possède pas les décorations définies comme une collection:

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

Mais le processus clone fonctionnerait si le xaml serait comme ceci:

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

J'ai trouvé une solution de contournement, quelque chose avec remplacement de chaîne:

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

mais je pense qu'il est vraiment sale, et j'aprécier si vous pouvez fournir une solution plus propre (en spécifiant un attribut pour la propriété Décorations par exemple)

Répondre

0

Avez-vous essayé d'appliquer la attribut suivant à la propriété Décorations:

[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] 
Questions connexes