bool as datasource for a CheckBox (Bool update in an other thread than the one it is impacting)
Asked Answered
L

2

6

I try to find how to assign a bool to a checkbox. I want that my checkbox.checked value refresh automatically when my bool data change. I know that for ComboBox there are the DataSource attribute that make it with a list but I am not able to find the equivalent with checkbox.

I try with the checkBox.DataBindings but it does not seem to work.On the other hand I don't really know what mean the third attribute.

checkBox.DataBindings.Add("Checked", DisableBugWatcher, "check");

I need that because I have two independent windows that refresh the same checkbox value!

EDIT :

I try to use the Event to update my main GUI but it say : Cross-thread operation not valid: Control 'checkBox' accessed from a thread other than the thread it was created on.

The problem is link to the fact that the bool value is refresh from an other thread than the one that it impact.

Lutero answered 6/3, 2013 at 19:52 Comment(2)
please tag your questions properly. If you're dealing with winforms tag the question winforms. FYI, there are many UI frameworks within .net, winforms is only one of them (the less performant, less scalable, less efficient one, by the way)Fester
possible duplicate of Bound checkbox does not update its datasourceBelie
L
1

I find an easier way with a friend to solve my problem. I use the DialogResult from my form.When I come back from the form it give me the state of the button click and it give me the value of the textbox. The same code works with my checkbox problem.

Here is an exemple of the code :

public partial class MainWindow : Form
{

    private OtherWindow m_otherWindow;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // Lazy create other window if it doesn't exist.
        m_otherWindow = m_otherWindow ?? new OtherWindow();

        // Passe textbox value to other window.
        m_otherWindow.PassedValue=textBox1.Text;
        if (m_otherWindow.ShowDialog()==DialogResult.OK)
        {
            // Clicked ok : update textbox value with textbox value of other window.
            textBox1.Text=m_otherWindow.PassedValue;
        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        Close();
    }
}

public partial class OtherWindow : Form
{

    /// <summary>
    /// Value to be passed to the window.
    /// </summary>
    public string PassedValue
    {
        get { return textBox1.Text; }
        set { textBox1.Text = value; }
    }

    public OtherWindow()
    {
        InitializeComponent();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        DialogResult = DialogResult.OK;
    }
}
Lutero answered 7/3, 2013 at 19:46 Comment(0)
W
4

To make DataBindings work, you have to implement INotifyPropertyChange in the class that contains your bool value. If you are hitting myValue from a thread other than the UI thread, you will have to use a SynchronizationContext and initialize myObject in the UI thread.

public class myObject : INotifyPropertyChanged
{
    // The class has to be initialized from the UI thread
    public SynchronizationContext context = SynchronizationContext.Current;

    bool _myValue;
    public bool myValue
    {
        get
        {
            return _myValue;
        }
        set
        {
            _myValue = value;

            // if (PropertyChanged != null)
                // PropertyChanged(this, new PropertyChangedEventArgs("myValue"));

            if (PropertyChanged != null)
            {
                context.Send(
                    new SendOrPostCallback(o => 
                       PropertyChanged(this, new PropertyChangedEventArgs("myValue"))
                    ), null);
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
}

Then, set your DataBinding as this :

checkBox1.DataBindings.Add("Checked", myObject.GlobalObject, "myValue");

The first parameter is the property of the UI object you want to bind to. The second attribute is your target object instance, the third is the property name of the target object that needs to be bound to the first.

I tried my best to reflect your scenario using a timer that toggle myValue each second (which check the checkbox accordingly). Here is the code of the Form I used:

System.Timers.Timer x = new System.Timers.Timer();
myObject target;

public Form1()
{
    InitializeComponent();

    target = new myObject();

    x.Elapsed += (s, e) =>
        {
            target.myValue = !target.myValue;
        };
    x.Interval = 1000;

    checkBox1.DataBindings.Add("Checked", target, "myValue");

    x.Start();
}
Whity answered 7/3, 2013 at 6:47 Comment(3)
Your answer would work perfectly for a program that works on only one thread. My problem is that I can not notify a thread from an other one. So my program tell me : Cross-thread operation not valid: Control 'checkBox' accessed from a thread other than the thread it was created on. See edit for more information.Lutero
This is more tricky than it appears... You have to use a Synchronization context and instanciate myObject in the UI thread (I did in the form constructor). Then I used a Timer to toggle myValue, which updates the checkbox accordingly. Hope it helps.Whity
Thank you ,with small modification because of my program, it works well!!Lutero
L
1

I find an easier way with a friend to solve my problem. I use the DialogResult from my form.When I come back from the form it give me the state of the button click and it give me the value of the textbox. The same code works with my checkbox problem.

Here is an exemple of the code :

public partial class MainWindow : Form
{

    private OtherWindow m_otherWindow;

    public MainWindow()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        // Lazy create other window if it doesn't exist.
        m_otherWindow = m_otherWindow ?? new OtherWindow();

        // Passe textbox value to other window.
        m_otherWindow.PassedValue=textBox1.Text;
        if (m_otherWindow.ShowDialog()==DialogResult.OK)
        {
            // Clicked ok : update textbox value with textbox value of other window.
            textBox1.Text=m_otherWindow.PassedValue;
        }
    }

    private void button2_Click(object sender, EventArgs e)
    {
        Close();
    }
}

public partial class OtherWindow : Form
{

    /// <summary>
    /// Value to be passed to the window.
    /// </summary>
    public string PassedValue
    {
        get { return textBox1.Text; }
        set { textBox1.Text = value; }
    }

    public OtherWindow()
    {
        InitializeComponent();
    }

    private void button2_Click(object sender, EventArgs e)
    {
        DialogResult = DialogResult.OK;
    }
}
Lutero answered 7/3, 2013 at 19:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.