Reputation: 1719
I would like a text field in my xaml to be bound to a property PlayerData.Instance.data.MyXP
The class structure is like this
class PlayerData
{
public static PlayerData Instance = new PlayerData();
public UserData data {get;set;}
}
class UserData
{
public int MyXP {get;set;}
}
Can someone explain how (if at all) I can do this. I have tried multiple methods from questions on SO and not found any that were successful. The biggest problem I have is that PlayerData.Instance.data is assigned AFTER the UI is created so I need some kind of notify event on UserData maybe but also on MyXP as I want the UI to update when the xp changes.
Upvotes: 1
Views: 1321
Reputation: 29790
You need to implement INotifyPropertyChanged
and set DataContext
of the TextBlock
to your instance:
class PlayerData
{
public static PlayerData Instance = new PlayerData();
private UserData data = new UserData();
public UserData Data
{
get { return data; }
set { data = value; }
}
}
class UserData : INotifyPropertyChanged
{
private int myXP = 0;
public int MyXP
{
get { return myXP; }
set
{
myXP = value;
RaiseProperty("MyXP");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaiseProperty(string property = null)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
In XAML you can do it like this:
<TextBlock Name="myExp" Text="{Binding Data.MyXP}" Grid.Row="2"/>
And to make it work you need to set the DataContext
of the TextBlock
to your instance:
myExp.DataContext = PlayerData.Instance;
Then you can freely chenge your XP and you should see it it the UI:
PlayerData.Instance.Data.MyXP = 1000;
You can also make your PlayerData : INotifyPropertyChanged
in case you have other data bound somewhere. Hopefully this example will show you how it works.
Upvotes: 1
Reputation: 8614
Usually, when you use a singleton, each object that uses it gets a copy of the Instance property. You could create a property on your View Model object that holds that reference and then you would bind to that property. For example:
public class MyViewModel : ViewModelBase {
public PlayerData PlayerData {
get { return iPlayerData; }
set {
iPlayerData = value;
OnPropertyChanged( "PlayerData" );
}
}
private PlayerData iPlayerData;
// Other properties & code
}
Then, in your XAML, assuming you've bound the Window
object's DataContext
property to the View Model object already, you would use something like this:
<TextBlock Text="{Binding Path=PlayerData.data.MyXP}" />
You may also need to specify an object that implements the IValueConverter
interface to format the int MyXP property properly.
(Note that your code, as shown, is not a valid implementation of the singleton pattern if you have a multi-threading environment. See this article and look at the section title "IVth way of implementing Singleton Pattern in C#: Multithreaded Singleton Pattern" if your code is multi-threaded).
Upvotes: 5