I have a class that defines a preconfigured socket and all the methods needed to access and control a specific piece of equipment remotely. Part of the class includes an instance of an object that holds the current status of various aspects of the equipment. Each item in the object reports updates using INotifyPropertyUpdate. When I plug it into my test program, all of the methods are called and execute properly, but the only way I seem to be able to get updates of the status to show in the UI is when the DataContext is set to the "Current" object inside the instance of the class. If I set the DataContext to the instance of the class, or to the UI, I stop getting updates in the UI. I would like to be able to use the UI as the DataContext and then bind in the XAML using {Binding Path=InstanceOfMyClass.Current.StatusItemA}
The pertinent parts of the classes in question:
public MyClass : Socket, INotifyPropertyChanged // INotifyPropertyChanged is also used to notify changes in other parts of the class
{
public MyClass : base(//socket configuration info here)
{}
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private CurrentStatusObject _current = new CurrentStatusObject();
public CurrentStatusObject Current
{
get { return _current; }
set
{
if (_current != value)
{
_current = value;
NotifyPropertyChanged();
}
}
}
// other methods and properties etc.
}
// this is the Current status object
public class CurrentStatusObject : object, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void NotifyPropertyChanged([CallerMemberName] string propertyName = "")
{
if (PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private string _statusItemA;
public string StatusItemA
{
get { return _statusItemA; }
set
{
if (_statusItemA != value)
{
_statusItemA = value;
NotifyPropertyChanged(); // not necessary to pass property name because of [CallerMemberName]
}
}
}
This works:
c#
this.DataContext = this.InstanceOfMyClass.Current;
XAML
<Label Content="{Binding Path=StatusItemA, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
This does not work, but I want it to:
c#
this.DataContext = this;
XAML
<Label Content="{Binding Path=InstanceOfMyClass.Current.StatusItemA, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"/>
Nor does this:
c#
this.DataContext = this.InstanceOfMyClass;
XAML
<Label Content="{Binding Path=Current.StatusItemA, Mode=OneWay, UpdateSourceTrigger}"/>
I didn't see any answers when searching, but sometimes my research skills fail me. Any help would be appreciated. I enjoy learning new ways of coding. This is my first c# or wpf project. All my projects previous to this have been vb.net in WinForms so I'm at a slight handicap with the learning curve. I would like to learn the correct way to reach my goals for this project, which at this point is simply completing the UI.
The CurrentStatusObject notifies changes internally and that does work. The problem is that the changes are only reflected in the User Interface if I set the DataContext for the UI to that one object. I want to be able to set the DataContext to include a wider scope. I would be happy if I could use the instance of MyClass as the DataContext, but that is not working right now.
The question is Why? and How do I get it to work (using correct practices)?
You can only bind to Properties, never fields.
InstanceOfMyClass
and Current
needs to be declared as properties before you can bind to it (to make DataContext = this
work).
As an aside, MVVM dictates that you shouldn't be using your View code-behind as the view model. You should have a separate class for that.