简体   繁体   中英

How to save custom class in C# WPF?

I'm developing a WPF application and I'm trying to do it without any reference to Windows Forms. I'm actually using the Wpf Font Picker by Alessio Saltarin which is a font picker with color picker completely developed in WPF.

What I'm trying to do is to let the user choose a font+color and save their choice in order to restore it for a new start of the application. The font is stored in the FontInfo class:

public class FontInfo
{
    public SolidColorBrush BrushColor { get; set; }
    public FontColor Color { get { return AvailableColors.GetFontColor(this.BrushColor); } }
    public FontFamily Family { get; set; }
    public double Size { get; set; }
    public FontStretch Stretch { get; set; }
    public FontStyle Style { get; set; }
    public FontWeight Weight { get; set; }

    public FamilyTypeface Typeface
    {
        get
        {
            FamilyTypeface ftf = new FamilyTypeface()
            {
                Stretch = this.Stretch,
                Weight = this.Weight,
                Style = this.Style
            };
            return ftf;
        }
    }

    public FontInfo() { }

    public FontInfo(FontFamily fam, double sz, FontStyle style, FontStretch strc, FontWeight weight, SolidColorBrush c)
    {
        this.Family = fam;
        this.Size = sz;
        this.Style = style;
        this.Stretch = strc;
        this.Weight = weight;
        this.BrushColor = c;
    }

    public static void ApplyFont(Control control, FontInfo font)
    {
        control.FontFamily = font.Family;
        control.FontSize = font.Size;
        control.FontStyle = font.Style;
        control.FontStretch = font.Stretch;
        control.FontWeight = font.Weight;
        control.Foreground = font.BrushColor;
    }

    public static FontInfo GetControlFont(Control control)
    {
        FontInfo font = new FontInfo()
        {
            Family = control.FontFamily,
            Size = control.FontSize,
            Style = control.FontStyle,
            Stretch = control.FontStretch,
            Weight = control.FontWeight,
            BrushColor = (SolidColorBrush)control.Foreground
        };
        return font;
    }

    public static string TypefaceToString(FamilyTypeface ttf)
    {
        StringBuilder sb = new StringBuilder(ttf.Stretch.ToString());
        sb.Append("-");
        sb.Append(ttf.Weight.ToString());
        sb.Append("-");
        sb.Append(ttf.Style.ToString());
        return sb.ToString();
    }
}

I didn't get the point about what is the best option. I saw that it can be achieved by XML Serialization but I failed and I saw that every example is using simple classes with strings and int variables.

Cold you please point me to some documentation or give me an example on how to do this?

You were on the right track with serialization, but it can be tricky at times. Here is a quick example you can try with your class that should work. This takes advantage of binary serialization.

First thing you must always do is make your class Serializable with an attribute like so.

[Serializable] //Add this attribute above your class
public class FontInfo
{
   //...
}

Next try this simple example to see if your class serializes, saves to a file then deserializes.

using System.Runtime.Serialization.Formatters.Binary;
using System.IO;

public void Example()
{
     FontInfo fi = new FontInfo(){Size = 12};

     BinaryFormatter bf = new BinaryFormatter();

     // Serialize the Binary Object and save to file
     using (FileStream fsout = new FileStream("FontInfo.txt", FileMode.Create, FileAccess.Write, FileShare.None))
     {
            bf.Serialize(fsout, fi);
     }

     //Open saved file and deserialize
     using (FileStream fsin = new FileStream("FontInfo.txt", FileMode.Open, FileAccess.Read, FileShare.None))
     {
         FontInfo fi2 = (FontInfo)bf.Deserialize(fsin);
         Console.WriteLine(fi2.Size); //Should output 12

     }
}

This is just a quick example, but should get your started on the right track.

As types like SolidColorBrush are not decorated with the SerializableAttribute they don't serialize by default. Therefore you have do do it manually by implementing the ISerializable interface and converting those types into a serializable format eg, string . This can be accomplished by using the build-in library converters that exist for almost all those types.

[Serializable]
public class FontInfo : ISerializable
{
  public FontInfo()
  {
    // Empty constructor required to compile.
  }

  public SolidColorBrush BrushColor { get; set; }
  //public FontColor Color { get { return AvailableColors.GetFontColor(this.BrushColor); } }
  public FontFamily Family { get; set; }
  public double Size { get; set; }
  public FontStretch Stretch { get; set; }
  public FontStyle Style { get; set; }
  public FontWeight Weight { get; set; }

  public FamilyTypeface Typeface => 
    new FamilyTypeface()
    {
      Stretch = this.Stretch,
      Weight = this.Weight,
      Style = this.Style
    };


  // Implement this method to serialize data. The method is called 
  // on serialization e.g., by the BinaryFormatter.
  public void GetObjectData(SerializationInfo info, StreamingContext context)
  {
    // Use the AddValue method to specify serialized values.
    info.AddValue(nameof(this.BrushColor), new ColorConverter().ConvertToString(this.BrushColor.Color), typeof(string));
    info.AddValue(nameof(this.Family), new FontFamilyConverter().ConvertToString(this.Family), typeof(string));
    info.AddValue(nameof(this.Stretch), new FontStretchConverter().ConvertToString(this.Stretch), typeof(string));
    info.AddValue(nameof(this.Style), new FontStyleConverter().ConvertToString(this.Style), typeof(string));
    info.AddValue(nameof(this.Weight), new FontWeightConverter().ConvertToString(this.Weight), typeof(string));
    info.AddValue(nameof(this.Size), this.Size, typeof(double));
  }


  // The special constructor is used 
  // e.g. by the BinaryFormatter to deserialize values.
  public FontInfo(SerializationInfo info, StreamingContext context)
  {
    // Reset the property value using the GetValue method.
    this.BrushColor = new SolidColorBrush((Color) ColorConverter.ConvertFromString((string)info.GetValue(nameof(this.BrushColor), typeof(string))));
    this.Family = (FontFamily) new FontFamilyConverter().ConvertFromString((string)info.GetValue(nameof(this.Family), typeof(string)));
    this.Stretch = (FontStretch) new FontStretchConverter().ConvertFromString((string)info.GetValue(nameof(this.Stretch), typeof(string)));
    this.Style = (FontStyle) new FontStyleConverter().ConvertFromString((string)info.GetValue(nameof(this.Style), typeof(string)));
    this.Weight = (FontWeight) new FontWeightConverter().ConvertFromString((string)info.GetValue(nameof(this.Weight), typeof(string)));
    this.Size = (double) info.GetValue(nameof(this.Size), typeof(double));
  }
}

Usage

public static void SerializeItem(string fileName)
{
  var fontInfo = new FontInfo();

  using (FileStream fileStream  = File.Create(fileName))
  {
    var formatter = new BinaryFormatter();
    formatter.Serialize(fileStream, fontInfo);
  }
}

public static void DeserializeItem(string fileName)
{     
  using (FileStream fileStream  = File.OpenRead(fileName))
  {
    var formatter = new BinaryFormatter();
    FontInfo fontInfo = (FontInfo) formatter.Deserialize(fileStream);
  }       
}       

Note

I don't know what FontColor is - must be a custom type of yours. In this case you need to decorate it with the SerializableAttribute too in order to serialize it (or provide a converter).

I didn't tested the code. Use this as a guide on how to serialize by implementing ISerializable .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM