0
votes

I have a class Project that I'm loading via serialization. I'm storing an instance of this class in a property LoadedProject. I'm attempting to bind a label to a property of Project called ProjectName. Until serialization is complete LoadedProject is null.

I understand I have to set the DataContext for PropertyChanged to not be null, but setting the DataContext before serialization results in DataContext being null. Setting it after serialization misses the event.

If I'm binding to a child property, where should I set the DataContext if the parent is null?

Project class:

public class Project : INotifyPropertyChanged
{
    private string _projectFilePath;

    internal string ProjectFilePath 
    { 
        get { return _projectFilePath; }
        set
        {
            _projectFilePath = value;
            this.OnPropertyChanged("ProjectName");
        }
    }

    public string ProjectName
    {
        get { return Path.GetFileNameWithoutExtension(ProjectFilePath); }
    }

    internal static Project Load(string fileName)
    {
        using (var stream = File.OpenRead(fileName))
        {
            var ds = new DataContractSerializer(typeof(Project));
            return ds.ReadObject(stream) as Project;
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    void OnPropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(
                this, new PropertyChangedEventArgs(propName));
    }
}

Main.xaml.cs

private Project LoadedProject { get; set; }
...
bool? result = dlg.ShowDialog();
if (result == true)
{
    // Open document 
    string filename = dlg.FileName;
    DataContext = LoadedProject;  //LoadedProject is currently null. Assigning the DataContext here will not work
    LoadedProject = Project.Load(filename);
}
...

XAML:

 <Label Content="{Binding Path=ProjectName, UpdateSourceTrigger=PropertyChanged, FallbackValue='No Project Loaded'}"></Label>

Edit 1: Must bind to public properties. Changed ProjectName from internal to public. Initial binding now works. PropertyChanged still null.

2
How about DataContext = Project.Load(filename);? Otherwise LoadedProject should be a property in another view model class. - Clemens
@Clemens The propertychange event is fired during serialization, at which point the DataContext is still null. Assigning DataContext after load will still miss the propertychange event. - Brandon

2 Answers

1
votes

I see that your LoadedProject is private, this will certainly cause some binding issues. First ensure that the property is set to public.

public Project LoadedProject { get; set; }

Assuming that you are binding directly to the LoadedProject property, you simply need to implement INotifyPropertyChanged on this property:

private Project _LoadedProject;

    public Project LoadedProject
    {
        get { return _LoadedProject; }
        set 
        { 
            _LoadedProject = value;
            OnPropertyChanged("LoadedProject");
        }
    }

This will force your UI to refresh the bindings to this object when it is loaded.

-1
votes

You will need to populate the Project outside of the view/viewmodel it is bound to

you could move the label to a sub view/control or have some start up logic