bool 作为 CheckBox 的数据源(在其他线程中进行 Bool 更新,而不是它影响的线程)

Posted

技术标签:

【中文标题】bool 作为 CheckBox 的数据源(在其他线程中进行 Bool 更新,而不是它影响的线程)【英文标题】:bool as datasource for a CheckBox (Bool update in an other thread than the one it is impacting) 【发布时间】:2013-02-21 19:05:27 【问题描述】:

我试图找到如何将布尔值分配给复选框。我希望我的 checkbox.checked 值在我的布尔数据更改时自动刷新。我知道对于 ComboBox 有一个 DataSource 属性,它用一个列表组成,但我找不到复选框的等价物。

我尝试使用 checkBox.DataBindings,但它似乎不起作用。另一方面,我真的不知道第三个属性是什么意思。

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

我需要它,因为我有两个独立的窗口可以刷新相同的复选框值!

编辑:

我尝试使用事件来更新我的主 GUI,但它说:跨线程操作无效:控件'checkBox'从创建它的线程以外的线程访问。

问题在于 bool 值是从其他线程刷新的事实,而不是它影响的线程。

【问题讨论】:

请正确标记您的问题。如果您正在处理 winforms 标记问题winforms。仅供参考,.net 中有许多 UI 框架,winforms 只是其中之一(顺便说一下,性能较差、可扩展性较差、效率较低的一个) Bound checkbox does not update its datasource的可能重复 【参考方案1】:

要使 DataBindings 工作,您必须在包含您的 bool 值的类中实现 INotifyPropertyChange。如果您从 UI 线程以外的线程访问 myValue,则必须使用 SynchronizationContext 并在 UI 线程中初始化 myObject。

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;

然后,将您的 DataBinding 设置为:

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

第一个参数是要绑定的 UI 对象的属性。第二个属性是你的目标对象实例,第三个是需要绑定到第一个的目标对象的属性名。

我已尽力使用每秒切换 myValue 的计时器(相应地选中复选框)来反映您的情况。这是我使用的表单的代码:

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();

【讨论】:

您的答案对于仅在一个线程上运行的程序非常有效。我的问题是我无法通知另一个线程。所以我的程序告诉我:跨线程操作无效:控件'checkBox'从创建它的线程以外的线程访问。有关更多信息,请参阅编辑。 这比看起来更棘手...您必须使用同步上下文并在 UI 线程中实例化 myObject(我在表单构造函数中做了)。然后我使用 Timer 来切换 myValue,从而相应地更新复选框。希望对您有所帮助。 谢谢,因为我的程序做了一点小改动,效果很好!!【参考方案2】:

我和朋友一起找到了一种更简单的方法来解决我的问题。我使用表单中的 DialogResult。当我从表单返回时,它给了我按钮单击的状态,它给了我文本框的值。相同的代码适用于我的复选框问题。

以下是代码示例:

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;
    

【讨论】:

以上是关于bool 作为 CheckBox 的数据源(在其他线程中进行 Bool 更新,而不是它影响的线程)的主要内容,如果未能解决你的问题,请参考以下文章

vue checkbox 布尔值互转01

datagridview中使用checkbox问题。

如何正确使用带有if语句的bool?

wpf ListView 中checkBox全选 如何实现?

SqlDataReader将Binary列转换为bool

extjs grid 中 如何根据数据动态给checkbox赋值