【问题标题】:How to save custom class in C# WPF?如何在 C# WPF 中保存自定义类?
【发布时间】:2020-03-01 06:36:38
【问题描述】:

我正在开发一个 WPF 应用程序,并且我正在尝试在不参考 Windows 窗体的情况下执行此操作。我实际上使用的是Wpf Font Picker by Alessio Saltarin,它是一个字体选择器,带有完全在 WPF 中开发的颜色选择器。

我想要做的是让用户选择一种字体+颜色并保存他们的选择,以便恢复它以重新启动应用程序。字体存储在 FontInfo 类中:

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

我没有明白什么是最佳选择。我看到它可以通过 XML 序列化来实现,但我失败了,我看到每个示例都使用带有字符串和 int 变量的简单类。

请给我一些文档或者给我一个例子来说明如何做到这一点?

【问题讨论】:

标签: c# wpf class save settings


【解决方案1】:

由于像SolidColorBrush 这样的类型没有用SerializableAttribute 修饰,它们默认不会序列化。因此,您必须通过实现ISerializable 接口并将这些类型转换为可序列化格式(例如string)来手动完成。这可以通过使用几乎所有这些类型都存在的内置库转换器来完成。

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

用法

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

注意

我不知道FontColor 是什么——一定是你的自定义类型。在这种情况下,您还需要使用SerializableAttribute 对其进行装饰,以便对其进行序列化(或提供转换器)。

我没有测试代码。以此为指导,了解如何通过实现ISerializable 进行序列化。

【讨论】:

  • 你好@BionicCode。您的代码完美运行!我不知道如何使用 ISerializable 接口。现在看起来很简单。非常感谢您的宝贵帮助。
【解决方案2】:

您在序列化方面走在了正确的轨道上,但有时可能会很棘手。这是一个简单的示例,您可以尝试使用应该可以工作的课程。这利用了二进制序列化。

您必须始终做的第一件事是使您的类Serializable 具有这样的属性。

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

接下来试试这个简单的例子,看看你的类是否序列化、保存到文件然后反序列化。

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

     }
}

这只是一个简单的示例,但应该能让您走上正确的道路。

【讨论】:

  • 非常感谢您的回答。我尝试了您的解决方案,但出现错误,因为 FontInfo 中使用的其他类(例如 SolidColorBrush)在其命名空间中不可序列化。我应该怎么得到这个?我对这些东西很陌生。非常感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 2013-04-14
  • 2012-10-09
  • 1970-01-01
  • 2013-03-14
  • 1970-01-01
  • 2022-12-17
  • 2010-12-01
  • 1970-01-01
相关资源
最近更新 更多