Home > Software design >  WPF text binding from variable changing in separate class/namespace
WPF text binding from variable changing in separate class/namespace

Time:11-25

I am struggling with Text binding in my WPF app.

  1. Lets imagine that I have another working app (ex. windows service) with some data in it.
  2. 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
  3. 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.

  1. 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; } 
        }
    }
}
  1. 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;
        }
    }
}
  1. 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
    }
}
  1. 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.

  1. Let the Mainwindow implement INotifyPropertyChanged

  2. 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;
     }
    
  3. 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;
} 
  • Related