Search code examples
c#serializationdata-bindinguwp

Using OneWay Binding (to keep DataGrid updated with PropertyChanged) breaks serialization


On my app, I'm using a DataGrid to display the status of some pieces of information from a class I've created. One of the columns describes the amount of time that has passed since I last updated a part of the class. This is done by using a property that compares a DateTime variable and returns a string describing the amount of time that has passed (x hours, minutes, etc) since that event. I use INotifyPropertyChanged on this string property once every second to keep this up to date.

When making changes in my app, I need it to save the state of all the data in my class, and I use binaryFormatter.Serialize for this. When the DataGrid Column's binding is set to Mode=OneWay, the information in the DataGrid refreshes every second exactly as I want, but the serialize operation fails when trying to save the data, telling me "serializing delegates is not supported on this platform". If I take out the Mode=OneWay, serializing works just fine, but the DataGrid no longer updates this information every second. Curiously, if I click the cell with this information a few times, the data is refreshed, but it does not refresh automatically on screen. Re-navigating to the page also obviously updates the data.

Here is the XAML for the DataGrid Column

<controls:DataGridTemplateColumn Header="Last Update">
    <controls:DataGridTemplateColumn.CellTemplate>
            <DataTemplate x:DataType="local:Network">
                    <TextBlock Text="{x:Bind LastUpdate}" Margin="15" Opacity="0.65" FontSize="12" VerticalAlignment="Center"/>
            </DataTemplate>
    </controls:DataGridTemplateColumn.CellTemplate>
</controls:DataGridTemplateColumn>

Here is the part of the class it refers to:

    DateTime _lastupdate;

    public string LastUpdate
    {
        get
        {
            TimeSpan diference = (DateTime.Now - _lastupdate);

            if (diference.TotalHours > 24)
            {
                return " (updated " + diference.Days + " Days ago)";
            }
            else if (diference.TotalMinutes > 60)
            {
                return " (updated " + diference.Hours + " Hours ago)";
            }
            else if (diference.TotalSeconds > 60)
            {
                return " (updated " + diference.Minutes + " Minutes ago)";
            }
            else
                return " (updated " + diference.Seconds + " Seconds ago)";
        }
    }

I'm honestly lost as to why this could be happening, and if I can't get this datagrid to update properly in real time, I'm not going to be able to implement a core part of the app that uses this DataGrid that I was planning for the future. Literally the only difference between a working app and a broken one is the Mode=OneWay. Functionally, the UI operates perfectly with OneWay, but it breaks the ability to save changes, so that's obviously a huge problem.


Solution

  • I figured it out! (Of course I figure it out myself after hours of googling before posting this)

    The issue apparently has something to do with INotifyPropertyChanged. I don't know why it doesn't cause a problem when I don't use the OneWay mode, but what solved it was this:

    [field:NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;
    

    I had tried [NonSerialized] before for the PropertyChanged event handler, but it claimed that I couldn't use it there, so I figured that wasn't serializable in the first place and so wasn't causing the issue.

    But then I found this page which listed [field:NonSerialized] as a solution:

    https://social.msdn.microsoft.com/Forums/vstudio/en-US/b3aa38fb-df9f-4dd0-b3dc-a767f8c8b620/problem-in-serialize-a-class-that-implements-inotifypropertychanged?forum=wpf

    and that solved it!