0
votes

In WPF I need to binary serialize a Polyline variable with a large number of points. I use the following code:

SaveFileDialog sf = new SaveFileDialog();
sf.FileName = "Orig.txt"); 

if (sf.ShowDialog() == true)
{
    FileStream fs = new FileStream(sf.FileName, FileMode.Create);
    BinaryFormatter formatter = new BinaryFormatter();

    try
    {
        formatter.Serialize(fs, plOriginal);
    }
    catch (Exception exc)
    {
        MessageBox.Show("Failed to serialize. Reason: " + exc.Message);
    }

    fs.Close();
}

but I get the error:

System.Runtime.Serialization.SerializationException: Type 'System.Windows.Media.PolyLineSegment' in Assembly 'PresentationCore, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' is not marked as serializable. at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter) at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph) at CurveAnalyzerDemoWPF.MainWindow.rbSave_Click(Object sender, RoutedEventArgs e) in MainWindow.xaml.cs:line 92}

So any workaround to make it work? thanx in advance

EDIT: I put the serializable attribute on the polyline variable:

[Serializable]
private PolyLineSegment plOriginal = new PolyLineSegment();

but I got the compilation following error: Error 1 Attribute 'Serializable' is not valid on this declaration type. It is only valid on 'class, struct, enum, delegate' declarations. F:\C# WPF\CurveAnalyzerDemoWPF\CurveAnalyzerDemoWPF\MainWindow.xaml.cs 55 4 CurveAnalyzerDemoWPF

1

1 Answers

1
votes

The message is quite self-explanatory. To use binary formater target class have to be marked with [Serializable] attribute. I suggest you to serialize data instead of 3rd party class instance. You can create your own class with [Serialiable] attribute to store points coordinates, build up polylines from it and update it's data if needed. And then just serialize your own class.

CS:

public partial class MainWindow : Window
{
    PolyLineData dataStorage = new PolyLineData();

    public MainWindow()
    {
        InitializeComponent();
        PopulateFromXaml();
        SaveToFile();
        LoadFromFile();
        PopulateToXaml();
    }

    private void PopulateToXaml()
    {
        polyLine.Points = new PointCollection(dataStorage.Points);
    }

    public void SaveToFile()
    {
        SaveFileDialog sf = new SaveFileDialog();
        sf.FileName = "Orig.txt";
        if (sf.ShowDialog() == true)
        {
            FileStream fs = new FileStream(sf.FileName, FileMode.Create);
            BinaryFormatter formatter = new BinaryFormatter();
            try
            {
                formatter.Serialize(fs, dataStorage);
            }
            catch (Exception exc)
            {
                MessageBox.Show("Failed to serialize. Reason: " + exc.Message);
            }
            fs.Close();
        }
    }

    public void LoadFromFile()
    {
        OpenFileDialog of = new OpenFileDialog();
        if ((bool)of.ShowDialog())
        {
            FileStream fs = new FileStream(of.FileName, FileMode.Open);
            BinaryFormatter bf = new BinaryFormatter();
            dataStorage = bf.Deserialize(fs) as PolyLineData;
            fs.Close();
        }
    }

    public void PopulateFromXaml()
    {
        foreach (var item in polyLine.Points)
        {
            dataStorage.Points.Add(item);
        }
    }

    [Serializable]
    public class PolyLineData
    {
        public List<Point> Points = new List<Point>();
    }
}

XAML:

 <Grid>
    <Polyline Stroke="LightBlue" 
              StrokeThickness="4" 
              Name="polyLine"
              Points="10,150 30,140 50,170 70,120 90,190 110,100 130,210 150,80 170,230 190,60 210,250 230,150 320,150" />
 </Grid>