I am struggling with Text binding in my WPF app.
- Lets imagine that I have another working app (ex. windows service) with some data in it.
- In my WPF app I would like to have folder "DATA" with class where data are introduced and in same folder another class which would include a void which will query my windows service
- I would like to show this data in my WPF window.
To make it simpler - one class with data, one class with data changing and WPF window with showing this data.
Unfortunately I can not achieve this... When I am executing below code, my window is showing 0 instead 123.
I would like to achive that my window will show value 123.
- file "Database.cs" in folder "Data" in project "example"
namespace example.Data
{
public class Database
{
private int _testInt = 0;
public int testInt
{
get { return _testInt; }
set { _testInt = value; }
}
}
}
- file "Query.cs" in folder "Data" in project "example"
namespace example.Data
{
public class Query
{
public Database _database;
public void execute()
{
_database = new Database();
_database.testInt = 123;
}
}
}
- file "MainWindow.xaml.cs" in project "example"
namespace example
{
public partial class MainWindow : Window
{
public Data.Database _database;
public Data.Query _query;
public int testInt
{
get { return _database.testInt; }
set { _database.testInt = value; OnPropertyChanged(); }
}
public MainWindow()
{
InitializeComponent();
DataContext = this;
_database = new Data.Database();
_query = new Data.Query();
_query.execute();
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
{
var e = new PropertyChangedEventArgs(propertyName);
handler(this, e);
}
}
#endregion
}
}
- File MainWindow.xaml
<Window>
<TextBlock Text="{Binding testInt}"
Foreground="White"
FontSize="15"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Margin="20,10,10,0" />
</Window>
P.S. If I will put
_database.testInt = 987;
to MainWindow.xaml.cs it is working properly - window is showing value 987 in textblock.
CodePudding user response:
You have multiple instances of the Database
object, a new one each time Query.execute
is called and one in MainWindow
constructor.
It's the data in the later that is displayed.
You should modify the content of this instance to see any change, for that, you must inject it in the Query
object:
_query = new Data.Query(_database);
// ...
public class Query
{
private readonly Database _database;
public Query(Database database)
{
_database = database;
}
public void Execute()
{
_database.testInt = 123;
}
}
Finally you need a way to notify the view that the content as changed, that why Database
should implement INotifyPropertyChanged
.
But at this point it's badly named, because it's a model in the MVVM pattern.
CodePudding user response:
you need to implement INotifyPropertyChanged
public partial class MainWindow : Window, INotifyPropertyChanged
CodePudding user response:
from the MVVM view, I think these answers from Orace and Jason are on a good way, both do not solve the problem completely.
Let the Mainwindow implement INotifyPropertyChanged
Let the query accept the new value:
public void execute(int value) { //_database = new Database(); // inject _database like in the answer above _database.testInt = value; }
When your
testInt
changes, let the_query
deliver the change down to the "database" (btw: you do it vice versa) See code below:`public int testInt {get { return _database.testInt; } `set { _query.execute(value); OnPropertyChanged(); }` } public MainWindow() { InitializeComponent(); DataContext = this; _database = new Data.Database(); // the property change will change both the view and the model testInt = 987; }
Well, you have changed both model and view with one property change then, Good or not?!
CodePudding user response:
Just for future users. There is small bug in Orace's answer: (It should be without "readonly" parameter, because below You are writing to it.
private Database _database;
public Query(Database database)
{
_database = database;
}