zoukankan      html  css  js  c++  java
  • [开源]FreeSCADA的通道数据与控件属性关联以及自动刷新机制研究

    【参考文章】:

    1. WPF之Binding深入探讨, 地址:http://www.cnblogs.com/cappuccino/p/3251631.html

    1. 几个重要的类列表:

    a) Designer工程下的CommonBindingDialog.cs:

    b) Designer工程下的NumericBindingPanel.cs(或者StringBindingPanel.cs):

    c) CommonGUI工程下的SchemaDocument.cs(LoadSchema()和SaveSchema())和RunTime工程下的ShemaView.cs(LoadDocument()):

    分别实现WPF界面的XMAL文件方式存储和XMAL文件方式载入,和实现WinForm下的WPF界面的载入。

    2. 通道数据与控件属性关联(以及自动刷新机制):

    a) 通道数据与控件属性绑定:

    CommonBindingDialog.cs中的事件响应方法(Create association按钮被按下):

    private void CreateAssociationButton_Click(object sender, EventArgs e)
    {
        SavePanelStateAndClose();
    
        if (propertyList.SelectedIndex >= 0 && bindingTypes.SelectedIndex >= 0)
        {
            BaseBindingPanelFactory factory = (BaseBindingPanelFactory)bindingTypes.SelectedItem; // factory在这里执行过后,就是NumericBindingPanel.cs里定义的NumericBindingPanelFactory类型了
            bindingPanel = factory.CreateInstance(); // bindingPanel的具体类型是NumericBindingPanel还是StringBindingPanel,在这里得到了重新定义(不再是基类的BaseBindingPanel类型了)
            bindingPanel.Initialize(element, propertyList.SelectedItem as PropertyWrapper, null);
            bindingPanel.Parent = panel1;
            bindingPanel.Dock = DockStyle.Fill;
            CreateAssociationButton.Enabled = false;
            bindingTypes.Enabled = false;
        }
    }

    CommonBindingDialog.cs中的事件响应方法(Save按钮被按下):

    private void saveButton_Click(object sender, EventArgs e)
    {
        SavePanelStateAndClose();
        if (activeBindings.Count > 0)
        {
            foreach (PropertyWrapper key in activeBindings.Keys)
            {
                DependencyObject depObj;
                DependencyProperty depProp;
                System.Windows.Data.BindingBase binding = activeBindings[key];
    
                if (key.GetWpfObjects(out depObj, out depProp) && binding != null)
                    BindingOperations.SetBinding(depObj, depProp, binding);
            }
        }
        DialogResult = DialogResult.OK;
        Close();
    }

    继续来看SavePanelStateAndClose方法的实现:

    private void SavePanelStateAndClose()
    {
        if (bindingPanel != null)
        {
            BindingBase binding = bindingPanel.Save(); // 见NumericBindingPanel类的Save()定义
            if (binding != null)
                activeBindings[bindingPanel.Property] = binding; // activeBindings为Dictionary<PropertyWrapper, BindingBase>,bindingPanel.Property为PropertyWrapper
    
            bindingPanel.Dispose();
            bindingPanel = null;
        }
    }

    我们再继续深入NumericBindingPanel.cs里面定义的Save方法:

    public override System.Windows.Data.BindingBase Save()
    {
        if (channel != null)
        {
            System.Windows.Data.Binding bind = new System.Windows.Data.Binding("Value");
            ChannelDataProvider cdp = new ChannelDataProvider();
            cdp.ChannelName = channel.PluginId + "." + channel.Name;
            bind.Source = cdp; // 绑定的源数据为通道数据
            bind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
            cdp.Refresh();
    
            ComposingConverter conv = new ComposingConverter();
            if (checkBox1.Checked)
            {
                RangeConverter rc = new RangeConverter();
                rc.Min = Decimal.ToDouble(minEdit.Value);
                rc.Max = Decimal.ToDouble(maxEdit.Value);
                conv.Converters.Add(rc);
            }
    
            conv.Converters.Add(new Kent.Boogaart.Converters.TypeConverter(cdp.Channel.Type, Property.PropertyType));
            bind.Converter = conv;
    
            bind.Mode = BindingMode.TwoWay;
    
            DependencyObject depObj;
            DependencyProperty depProp;
            if (Property.GetWpfObjects(out depObj, out depProp))
                bind.FallbackValue = depObj.GetValue(depProp);
    
            return bind;
        }
        else 
            return base.Save();
    }

    这里关键是WPF编程方式下System.Windows.Data.Binding类的使用,下面我们来看一个简单的WPF示例工程,该工程演示了WPF中一个TextBox的Text属性与

    数据源的绑定、以及子线程中绑定数据源值更新的自动同步:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    
    using System.Threading;
    using System.ComponentModel;
    
    namespace WpfApplication1
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public class DataSource : INotifyPropertyChanged
            {
                private int _index;
    
                public int Index
                {
                    get { return _index; }
                    set
                    {
                        _index = value;
                        if (PropertyChanged != null)
                        {
                            this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Index"));
                        }
                    }
                }
                public event PropertyChangedEventHandler PropertyChanged;
            } 
    
            System.Windows.Data.Binding _bind;
            Thread _thread;
            DataSource _dataSource;
            bool _run;
    
            public MainWindow()
            {
                InitializeComponent();
                
                _dataSource = new DataSource();
                // System.Windows.Data.Binding方式
                _bind = new System.Windows.Data.Binding();
                _bind.Source = _dataSource;
                _bind.Path = new PropertyPath("Index");
                _bind.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                this.textBox1.SetBinding(TextBox.TextProperty, _bind);
    
                _run = true;
                _thread = new Thread(Test);
                _thread.Start();
            }
    
            void Test()
            {
                while (_run) // 里面不能放阻塞式的方法,否则逻辑可能一直卡住
                {
                    _dataSource.Index++;
                    Thread.Sleep(100);
                }
            }
    
            private void Window_Closing(object sender, CancelEventArgs e)
            {
                _run = false;
                if (_thread != null)
                {
                    _thread.Join();
                    _thread = null;
                }
            }
    
        }
    }

    工程界面:

    实际运行界面:

     
  • 相关阅读:
    CSP 2020 提高组第一轮
    初赛胡扯
    Sublime安装SublimeServer插件开启本地服务器
    Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in XXX ode_modules@babelhelper-compilation-targetspackage.json
    Vue解决less-loader报错 TypeError: this.getOptions is not a function
    Vue-cli项目关闭eslint检查
    Typora添加主题
    Oracle存储过程中EXECUTE IMMEDIATE 执行结果是空时怎么继续执行
    存储过程--异常捕获
    git和github的基本使用(2)
  • 原文地址:https://www.cnblogs.com/jayhust/p/8377013.html
Copyright © 2011-2022 走看看