Home > Back-end >  How to programmatically bind a property?
How to programmatically bind a property?

Time:09-15

This is my code:

using MySqlConnector;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;

namespace Flanium_Agent
{
    public class Agency
    {
        public string Station { get; set; }
        public string Process { get; set; }
        public string Actions { get; set; }
        public string Started { get; set; }
        public string Finished { get; set; }
        public string Status { get; set; }
        public MySqlConnection connection =new MySqlConnection("Server=localhost;User ID=root;Database=orchestration_db");

        private Grid DisplayGrid { get; set; }

        private Border border { get; set; }

        public Grid getDisplayGrid()
        {
            return DisplayGrid;
        }
        public Agency InsertAgentToGrid(Grid grid)
        {

            DisplayGrid = new Grid();
            
            var headerRowDefinition = new RowDefinition();
            headerRowDefinition.Height = new GridLength(50);
            DisplayGrid.RowDefinitions.Add(headerRowDefinition);

            for (var index = 0; index < GetType().GetProperties().Length; index  )
            {
                var property = GetType().GetProperties()[index];
                var header = new TextBlock();
                var column = new ColumnDefinition();
                header.Text = property.Name;
                header.HorizontalAlignment = HorizontalAlignment.Center;
                header.VerticalAlignment = VerticalAlignment.Center;
                header.FontSize = 16;
                Grid.SetRow(header, 0);
                Grid.SetColumn(header, index);

                DisplayGrid.ColumnDefinitions.Add(column);
                DisplayGrid.Children.Add(header);
            }

            var contentRowDefinition = new RowDefinition();
            contentRowDefinition.Height = new GridLength(50);
            DisplayGrid.RowDefinitions.Add(contentRowDefinition);

            for (var index = 0; index < GetType().GetProperties().Length; index  )
            {
                var propertyValue = GetType().GetProperties()[index];
                var content = new TextBlock();
                
                //content.Text = propertyValue.GetValue(this).ToString();
                content.HorizontalAlignment = HorizontalAlignment.Center;
                content.VerticalAlignment = VerticalAlignment.Center;
                content.FontSize = 12;
                Grid.SetRow(content, 1);
                Grid.SetColumn(content, index);
                DisplayGrid.Children.Add(content);
                
                var myBinding = new Binding(propertyValue.Name)
                {
                    Source = this
                };
                content.SetBinding(TextBlock.TextProperty, myBinding);

            }

            DisplayGrid.HorizontalAlignment = HorizontalAlignment.Stretch;
            DisplayGrid.VerticalAlignment = VerticalAlignment.Top;
            DisplayGrid.Margin = new Thickness(0, 25, 0, 0);
            grid.Children.Add(DisplayGrid);
            
            connection.Open();
            //create new thread with UpdateAgent()
            Task.Run(UpdateAgent);
            

            return this;
        }

        public void UpdateAgent()
        {
            try
            {

                var cmd = new MySqlCommand("SELECT * FROM agents WHERE station='"   Station   "'", connection);
                var reader = cmd.ExecuteReader();
                
                reader.Read();
                Station = reader.GetString(0);
                Process = reader.GetString(1);
                Actions= reader.GetString(2);
                Started = reader.GetString(3);
                Finished = reader.GetString(4);
                Status = reader.GetString(5);
                reader.Close();

                
                Thread.Sleep(1000);
                Task.Run(UpdateAgent);

            }
            catch (Exception exception)
            {
                    
            }
        }
        public Agency(string station, string process, string actions, string started, string finished, string status)
        {
            try
            {
                Station = station;
                Process = process;
                Actions = actions;
                Started = started;
                Finished = finished;
                Status = status;

                connection.Open();

                var cmd = new MySqlCommand("INSERT INTO agents (station, process, actions, started, finished, status) VALUES (@station, @process, @actions, @started, @finished, @status)", connection);

                cmd.Parameters.AddWithValue("@station", station);
                cmd.Parameters.AddWithValue("@process", process);
                cmd.Parameters.AddWithValue("@actions", actions);
                cmd.Parameters.AddWithValue("@started", started);
                cmd.Parameters.AddWithValue("@finished", finished);
                cmd.Parameters.AddWithValue("@status", status);

                cmd.ExecuteNonQuery();
                connection.Close();
            }
            catch (Exception e)
            {

            }

        }

        public void RemoveAgent()
        {
            try
            {
                connection.Close();
                connection.Open();

                using var cmd = new MySqlCommand("DELETE FROM agents WHERE station = @station", connection);

                cmd.Parameters.AddWithValue("@station", Station);
            
                cmd.ExecuteNonQuery();

                connection.Close();
            }
            catch (Exception e)
            {
                connection.Close();
                
            }
            
        }

    }
}

I can confirm that the binding is set properly from these lines:

        var myBinding = new Binding(propertyValue.Name)
        {
            Source = this
        };
        content.SetBinding(TextBlock.TextProperty, myBinding);

Because even though I do not set the text property to a value with this: content.Text = propertyValue.GetValue(this).ToString(); because it is commented, the text value is still being updated.

However.. I have a recursive method that runs once every 1000ms called UpdateAgent(), this method reads from an mySQL Database and updates the class, now this is where I can't figure out why this text property of the content TextBlock will not update even though the class properties have, even with a binding already set.

I have already browsed and looked for duplicates but could not find anything relevant or anyone who tried using a recursive method to fetch data from an SQL database and their bindings not updating etc.

CodePudding user response:

WPF has no way of knowing that the property changed, and thus that the Binding is out-of-date.

You should implement INotifyPropertyChanged on the Agency class and broadcast an event when any property changes. As an optimisation, if you know you're changing all the properties at once, you can raise a single event (instead of one per property).

public class Agency : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public void UpdateAgent()
    {
        // ... elided for clarity

        // set all properties
        Station = reader.GetString(0);
        Process = reader.GetString(1);
        Actions= reader.GetString(2);
        Started = reader.GetString(3);
        Finished = reader.GetString(4);
        Status = reader.GetString(5);

        // ** ADD THIS CODE **
        // raise the PropertyChanged event so WPF updates bindings
        PropertyChanged.Invoke(this, new PropertyChangedEventArgs(""));

        // ... elided for clarity
    }
}
  • Related