简体   繁体   中英

c# WinForms DataBinding doesn't update my TextBox.text

I wanna bind a TextBox to a class property, so when this property changes, my TextBox changes automatically too (Windows Forms). I have a class like this:

class Device : INotifyPropertyChanged
{
    private string can_rpm;
    public string Can_rpm
    {
       get { return can_rpm; }
       set { can_rpm = value; NotifyPropertyChanged(); }
    }
   
    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    
    \\lots of other codes
}

My main form has some code like this (with a textbox called 'tbTest'):

private void Form1_Load(object sender, EventArgs e)
{
   Device device= device = new Device();
   tbTest.DataBindings.Clear();
   tbTest.DataBindings.Add(new Binding("Text",device,"Can_rpm",true,DataSourceUpdateMode.OnPropertyChanged));
   
   \\lots of other stuff         
}

My problem: My textBox never updates! A have some other code that updates the 'Can_rpm' property, but nothing shows on my textbox.text. BUT, if I change the empty value of my textbox to something else, my property DOES change too! So it's working 'one way', but not the other!

I've searched here and googled it, but all I find is examples that does what is already done in my code, but mine doesn't work.

Thanks for helping if you can.

Try with this:

tbTest.DataBindings.Add(nameof(TextBox.Text), device, nameof(Device.Can_rpm));

I've tested the code with your Device class code and this code in the form constructor:

var device = new Device();

this.textBox1.DataBindings.Add(nameof(TextBox.Text), device, nameof(Device.Can_rpm));
        
device.Can_rpm = "Hello";

After that, my textbox has "Hello" text.

UPDATE

You need update controls always in the thread in which they was created, usually in the main thread. I use a Form extension methods to do that:

public static class FormExtends
{
    public static void RunInMyThread(this Form form, Action operation)
    {
        if (form.InvokeRequired)
        {
            form.BeginInvoke(operation);
        }
        else
        {
            operation();
        }
    }
}

With the previous extension, you can do (in your Form code) your updates in this way:

this.RunInMyThread(() => device.Can_rpm = "Hello");

Another way to do that:

public class Device : INotifyPropertyChanged
{
    private static SynchronizationContext GuiContext = SynchronizationContext.Current;

    private string can_rpm;
    public string Can_rpm
    {
        get { return can_rpm; }
        set { can_rpm = value; NotifyPropertyChanged(); }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            GuiContext.Post(
                s => PropertyChanged(this, new PropertyChangedEventArgs(propertyName)), 
                null);
        }
    }
}

GuiContext is initialized in the main thread so it runs the code in that thread. If you change your PropertyChanged event to throw in the Post of that context, you don't need take care about where your device properties are changed because the notiy always run in the main thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM