繁体   English   中英

mono 上的 Winforms 数据绑定和 INotifyPropertyChanged

[英]Winforms data binding and INotifyPropertyChanged on mono

我已经让我的第一个 mono 应用程序在树莓派上运行。 问题是数据绑定没有更新 UI。 更具体地说,我的控制器/模型中的 PropertyChanged 事件是 null。这意味着没有订阅者。

当我在 windows 上运行 visual studio 调试器中的应用程序时,ui 得到正确更新。

Mono 版本:4.6.2 操作系统:Raspbian Wheezy .NET:4.5

我没有找到太多关于这种情况的信息。 由于它在 windows 和 mono 上工作,支持 INotifyPropertyChanged 接口,我假设它也会在 mono 上运行在 linux 上。

// creating the binding in code dhtControl.labelName.DataBindings.Add("Text", dht, "Name");

我认为不需要其他代码,因为它是默认的 INotifyPropertyChanged 实现。 唯一的区别是我将一个动作 (control.Invoke) 传递给 model 以调用主线程上的更新。

问候

我有同样的问题,解决了添加ViewModel触发的动作事件,其中更新了所有控件:

internal void InvokeUIControl(Action action)
    {
        // Call the provided action on the UI Thread using Control.Invoke() does not work in MONO
        //this.Invoke(action);

        // do it manually
        this.lblTemp.Invoke(new Action(() => this.lblTemp.Text = ((MainViewModel)(((Delegate)(action)).Target)).Temperature));
        this.lblTime.Invoke(new Action(() => this.lblTime.Text = ((MainViewModel)(((Delegate)(action)).Target)).Clock));           
    }

我注意到.NET和Mono之间存在差异,我遇到了同样的问题。 在比较.NET和Mono源代码之后,首先看来,如果您希望在ViewForm中收到任何Control.TextChanged中的propertyName通知,您首先必须在您的模型中:

    public event PropertyChangedEventHandler PropertyChanged;
    public event EventHandler TextChanged;

    protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
    {
        if (PropertyChanged != null)
        {
            if (propertyName == "Text")
            {
                TextChanged?.Invoke(this, EventArgs.Empty);
            }
        }
    }

将事件处理程序命名为“TextChanged”以通知TextChanged非常重要。 然后仍然在你的模型中,你可以设置:

    private string _Text = "";
    public string Text {
        get {
            return _Text;
        }
        set {
            if (_Text != value) {
                NotifyPropertyChanged ("Text");
            }
        }
    }

现在,在您看来,您可以做这样的事情。

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace EventStringTest
{
    public partial class Form1 : Form
    {
        Model md = Model.Instance;

        public Form1()
        {
            InitializeComponent();
            textBox1.DataBindings.Add("Text", md, "Text", false
                , DataSourceUpdateMode.OnPropertyChanged);
            this.OnBindingContextChanged(EventArgs.Empty);
            textBox1.TextChanged += (object sender, System.EventArgs e) => { };
        }

        private void Form1_Load(object sender, EventArgs evt)
        {
            md.PropertyChanged += (object s, PropertyChangedEventArgs e) => { };

            // This is just to start make Text Changed in Model.
            md.TimerGO ();
        }
    }
}

这似乎是很多代码,但我仍然在寻找一个优雅的更好的解决方案。

他们在这种情况下有什么新的经验吗? 我开始了一个新项目来为 Raspberry(RS232、GUI 和 http 行为/响应)开发一个远程应用程序并且不会改变我的编程语言 - C#。我在一些我不期望的点上获得了很多快速目标 - 串行和GPIO 与用 VS2022 编写的代码配合得很好——但我不希望此时出现停止标志。 触发 INotifyPropertyChanged 事件后,按钮上的简单文本不会更新。 就像这里描述的那样。 我发现,事件在主代码中被识别。 我为 ViewModel 事件订阅了一个委托,该委托被调用。

viewModel.PropertyChanged += UpdateLabel;

使用完整的小代码解决了初始问题(初学者失败)在这里

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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