Home > Net >  WPF TextBox doesn't refresh despite binding and INotifyPropertyChangeduse
WPF TextBox doesn't refresh despite binding and INotifyPropertyChangeduse

Time:01-02

I did a little WPF window with a button and a textBox.

When I click on the button, there is some stuff, then I add some lines to my TextBox.

I often did this kind of apps with Winform and when I did them, the UI refreshed each time the textbox was updated, but not in my WPF application.

So I read about and did binding and used the INotifyPropertyChanged.

public partial class MainWindow : MetroWindow, INotifyPropertyChanged
{ 
    public MainWindow()
    {
        InitializeComponent();
        this.DataContext = this;
    }

    private string myValue;
    public string MyValue
    {
        get { return myValue; }
        set
        {
            myValue = value;
            RaisePropertyChanged("MyValue");
        }
    }

    private void RaisePropertyChanged(string propName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
    public event PropertyChangedEventHandler PropertyChanged;

    // 
    //.......
    //
}

Then my XAML :

<TextBox  x:Name="TxtBox_result" Text="{Binding Path=MyValue}" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalScrollBarVisibility="Auto" AcceptsReturn="True" Margin="30,332,0,0"  VerticalAlignment="Top" Width="868" Height="285" TextChanged="TxtBox_result_TextChanged" />

I know there is probably cleaner code to do with MVVM approach but I don't know MVVM but would like to try first to have a simple method to refresh my UI. It's a shame because it was easier in Win32.


Here is the code executed when i click on the button, i update the MyValue on these code but the TextBox only show value when the treatment is over :

private void GenererBases (string DirectoryStd, string DirectorySur)
{
int cpt = 0;

bool bSignatureBaseFound = false;
bool bFirst = true;
string strDirectoryOut = string.Empty;

var files =  Directory.GetFiles(DirectorySur, "*.*", SearchOption.TopDirectoryOnly)
.Where(s => s.EndsWith(".txt") || s.EndsWith(".dat"));

MyValue = " ";
MyValue = " > Recherche des fichiers ...."   Environment.NewLine;

foreach (string fileName in files)
{
    string line = string.Empty;
    string FileNameStandard = string.Empty;
    bSignatureBaseFound = false;

    MyValue = MyValue   Environment.NewLine   " > Extraction de la signature du fichier base pour : "   System.IO.Path.GetFileName(fileName);


    System.IO.StreamReader file = new System.IO.StreamReader(fileName);
    while ((line = file.ReadLine()) != null)
    {
        if (line.Contains("SetModuleInfo('$Id:"))
        {
            bSignatureBaseFound = true;
            int posDebFichier = line.IndexOf("'$Id:")   6;
            int posFinFichier = line.IndexOf(" ", (line.IndexOf("'$Id:")   6));

            FileNameStandard = line.Substring(posDebFichier, posFinFichier-posDebFichier); 

            if (File.Exists(DirectoryStd @"\" FileNameStandard))
            {
                MyValue = MyValue   Environment.NewLine   " > Fichier base : "   FileNameStandard   " localisé ! > Copie vers le dossier de destination !";
                
                if (bFirst)
                {
                    strDirectoryOut = DirectorySur   @"\Generated_bases_"   DateTime.Now.ToString("yyyyMMddHHmm");
                    Directory.CreateDirectory(strDirectoryOut);
                    bFirst = false;
                }

                cpt  ;

                if (File.Exists(strDirectoryOut   @"\"   System.IO.Path.GetFileNameWithoutExtension(FileNameStandard)   "_base"   System.IO.Path.GetExtension(FileNameStandard)))
                {
                    File.Delete(strDirectoryOut   @"\"   System.IO.Path.GetFileNameWithoutExtension(FileNameStandard)   "_base"   System.IO.Path.GetExtension(FileNameStandard));
                }
                File.Copy(DirectoryStd   @"\"   FileNameStandard, strDirectoryOut   @"\"   System.IO.Path.GetFileNameWithoutExtension(FileNameStandard)   "_base"   System.IO.Path.GetExtension(FileNameStandard),true);
                File.SetAttributes(strDirectoryOut   @"\"   System.IO.Path.GetFileNameWithoutExtension(FileNameStandard)   "_base"   System.IO.Path.GetExtension(FileNameStandard), File.GetAttributes(strDirectoryOut   @"\"   System.IO.Path.GetFileNameWithoutExtension(FileNameStandard)   "_base"   System.IO.Path.GetExtension(FileNameStandard)) | FileAttributes.Hidden);

            }
            else
            {
                MyValue = MyValue   Environment.NewLine   "!!! WARNING!!"   Environment.NewLine   "!!! Fichier base non localisé : "   FileNameStandard   Environment.NewLine;
            }
            break;
        }
        
    }
    file.Close();

    if (bSignatureBaseFound==false)
    {
        MyValue = MyValue   Environment.NewLine   "!!! WARNING!!"   Environment.NewLine   "!!! Aucune signature de base localisée pour : "   fileName   Environment.NewLine;

    }
    
}

MyValue = MyValue   Environment.NewLine   "***************************"   Environment.NewLine   "***************************"   Environment.NewLine   " >> Fin du traitement !"   cpt   " fichiers bases générés pour "   files.Count()   " sources surchargés !"   Environment.NewLine   ">> Fichiers bases copiés dans le dossier :"   strDirectoryOut   Environment.NewLine;
}

Thanks a lot

CodePudding user response:

A simple example.

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls.Primitives;

namespace Core2022.SO.WalterFabioSimoni
{
    public partial class InpcWindow : Window, INotifyPropertyChanged
    {
        protected bool Set<T>(ref T propertyField, T newValue, [CallerMemberName] string? propertyName = null)
        {
            if (string.IsNullOrWhiteSpace(propertyName))
                throw new ArgumentNullException(nameof(propertyName));

            bool notEquals = !Equals(propertyField, newValue);
            if (notEquals)
            {
                propertyField = newValue;
                RaisePropertyChanged(propertyName);
            }

            return notEquals;
        }
        protected void RaisePropertyChanged([CallerMemberName] string? propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName ?? string.Empty));
        }

        public event PropertyChangedEventHandler? PropertyChanged;
    }
    public partial class AsyncUpdateWindow : InpcWindow
    {
        public AsyncUpdateWindow()
        {
            InitializeComponent();
        }
        private string _myValue = string.Empty;

        public string MyValue
        {
            get => _myValue;
            set => Set(ref _myValue, value ?? string.Empty);
        }

        private static readonly Random random= new Random();
        private async void OnRestartAsync(object sender, RoutedEventArgs e)
        {
            UIElement button = (UIElement)sender;
            button.SetCurrentValue(IsEnabledProperty, false);
            for (int i = 0; i < 10; i  )
            {
                MyValue = random.Next(int.MinValue, int.MaxValue).ToString();
                await Task.Delay(500);
            }
            button.InvalidateProperty(IsEnabledProperty);
        }
    }
}
<local:InpcWindow x:Class="Core2022.SO.WalterFabioSimoni.AsyncUpdateWindow"
                  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
                  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                  xmlns:local="clr-namespace:Core2022.SO.WalterFabioSimoni"
                  mc:Ignorable="d"
                  Title="AsyncUpdateWindow" Height="300" Width="400"
                  DataContext="{Binding RelativeSource={RelativeSource Self}}">
    <UniformGrid Columns="1">
        <Viewbox>
            <TextBlock Text="{Binding MyValue}" Margin="10"/>
        </Viewbox>

        <Button Content="Restart" Click="OnRestartAsync"/>
    </UniformGrid>
</local:InpcWindow>

There are no calls to UI elements in your method code - this is very good. For your code, you just need to add the following method:

    private async void GenererBasesAsync(string DirectoryStd, string DirectorySur)
        => await Task.Run(() => GenererBases(DirectoryStd, DirectorySur));

In the clicker, call this async method.

  • Related