• 枚举与Combox的SelectedIndex绑定出现怪异问题的解决方案


    在Combox中有一系列的选项,其选项的SelectedIndex值对应了相应的枚举值,而这些枚举值会影响着后续的工作模式,所以就想着将Combox的SelectedIndex和枚举值进行双向绑定,代码如下

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    
    //Add
    using System.Linq.Expressions;
    
    namespace ComboxBinding
    {
        public partial class FormMain : Form
        {
            public FormMain()
            {
                InitializeComponent();
            }
    
            private BindingDataProperyty _bindingDataProperty = null;
    
            private void FormMain_Load(object sender, EventArgs e)
            {
                for (int index = 0; index < 10; index++)
                {
                    comboBoxData.Items.Add(index.ToString());
                }
                
                _bindingDataProperty = new BindingDataProperyty();
                comboBoxData.DataBindings.Add("SelectedIndex",
                                            _bindingDataProperty,
                                            "Way_pro",
                                            false,
                                            DataSourceUpdateMode.OnPropertyChanged);
            }
    
            private void buttonShow_Click(object sender, EventArgs e)
            {
                MessageBox.Show(((WAYS)_bindingDataProperty.Way_pro).ToString());
            }
        }
    
        public enum WAYS
        {
            WAY0 = 0x00,
            WAY1 = 0x01,
            WAY2 = 0x02,
            WAY3 = 0x03,
            WAY4 = 0x04,
            WAY5 = 0x05,
            WAY6 = 0x06,
            WAY7 = 0x07,
            WAY8 = 0x08,
            WAY9 = 0x09
        }
    
        public class BindingDataProperyty : INotifyPropertyChanged
        { 
            #region Way Property
            private WAYS _way = 0;
            public WAYS Way_pro
            {
                get
                {
                    return _way;
                }
                set
                {
    
                    if (value == _way)
                    {
                        return;
                    }
                    _way = value;
                    NotifyPropertyChanged(() => Way_pro);
                }
            }
            #endregion
    
            #region Way NotifyPropertyChanged
            public void NotifyPropertyChanged<T>(Expression<Func<T>> property)
            {
                if (PropertyChanged == null)
                {
                    return;
                }
                var memberExpression = property.Body as MemberExpression;
                if (memberExpression == null)
                {
                    return;
                }
    
                PropertyChanged.Invoke(this, new PropertyChangedEventArgs(memberExpression.Member.Name));
            }
    
            public event PropertyChangedEventHandler PropertyChanged;
            #endregion
        }
    }
    
    代码正常运行,可是当我在Combox选择了项之后,要显示相应的工作方式时,怪异的事情发生了。请看下图1

    图1


    我明明在Combox上选择了4,结果一点Show之后,却弹出了WAY0,同时Combox却自动变成了0,这是怎么回事?这时不是应该弹出WAY4才对的吗?

    网上搜了一通之后,没有看到合适的解决方案。思来想去,问题可能是出在枚举的绑定上,那就先别用枚举来定义Way_pro了,先用int来。修改的代码如下

        public class BindingDataProperyty : INotifyPropertyChanged
        {
            #region Way Property
            private int _way = 0;
            public int Way_pro
            {
                get
                {
                    return _way;
                }
                set
                {
    
                    if (value == _way)
                    {
                        return;
                    }
                    _way = value;
                    NotifyPropertyChanged(() => Way_pro);
                }
            }
            #endregion        
    
           ...
        }
    
    

    代码中就是把Way_pro的类型由WAYS改成了int.下面是运行结果(图2)

    图2


    Combox选择了6,Show出来的是WAY6,结果达到了预期。

    这么看来,还真的是枚举引起的。目的达到了,但是为什么会引起这个问题,还是没有明白,于是进行了进一步的测试。

    将Way_pro的类型再改回成枚举WAYS,同时将初始值改成WAY9.修改的代码如下

        public class BindingDataProperyty : INotifyPropertyChanged
        {
            #region Way Property
            private WAYS _way = WAYS.WAY9;
            public WAYS Way_pro
            {
                get
                {
                    return _way;
                }
                set
                {
    
                    if (value == _way)
                    {
                        return;
                    }
                    _way = value;
                    NotifyPropertyChanged(() => Way_pro);
                }
            }
            #endregion        
             ...
        }
    
    
    下面是运行结果(图3)

    图3


    可以看到Combox的值为9,正是我们所绑定的值WAY9对应的SelectedIndex。这么看来,从枚举到SelectedIndex的绑定是OK的。

    再结合前面图1的结果,当我们选择了4之后,Show出来的结果却还是WAY0,同时Combox变成了0.这说明,双向绑定从SelectedIndex到枚举时出错了,导致我们在点击Show时,获取的是Way_pro的默认值(见图4),再次触发Way_pro,将Way_pro的默认值重新绑定到了Combox上,于是Combox又显示了默认值。

    图4


    那我们怎么证明从SelectedIndex到枚举的绑定出错了呢?我们知道,在双向绑定时,控件上的属性值发生改变时,会触发相应绑定属性的set方法,如SelectedIndex改变会触发Way_pro的set方法,如果不触发那就说明异常了(如类型转换失败引起的异常)。下面是两段代码debug的截图。

    图5


    图6


    从图5中我们可以看到,Combox的默认是WAY9,对应的SelectedIndex是9,当我们在Combox选择了5之后,Way_pro的set方法并没有被触发。而从图6中可以看到,Combox选择了5之后,Way_pro的set方法触发了,并且值value=5也值进去了。这就说明图5的方式出现了异常,所以set方法没有触发,而这个异常是SelectedIndex隐式转换成WAYS时出错了。

    如果只是进行单向绑定(也就是只改变Way_pro的值,Combox的SelectedIndex就会相应的改变),是可以直接将枚举与SelectedIndex绑定的。如图7

    图7


    所以综上,Combox的SelectedIndex与枚举可以直接单向绑定,但是不能直接双向绑定。如果要进行双向绑定,所绑定的属性必须定义成int类型,在取值时再强转成枚举类型。

    补充:对于Combox的数据绑定需要使用SelectItem,同时绑定的源需要附一个初始值。如果绑定的是SelectValue或者SelectText,有可能会出问题,特别是直接将数据源赋值到Combox.DataSource中时,SelectValue会为空值。参考代码如下

     private void FormMain_Load(object sender, EventArgs e)
            {
                ...//使用前面的代码
    	    _bindingDataProperty.Data_pro=1;//先赋一个初始值
                comboBoxData.DataBindings.Add("SelectedItem",
                                             _bindingDataProperty,
                                             "Data_pro",
                                             false,
                                             DataSourceUpdateMode.OnPropertyChanged);
    	   
            }  
    
    private void buttonShow_Click(object sender, EventArgs e)
            {           
                string info = string.Format("Data:{0}", _bindingDataProperty.Data_pro);
                MessageBox.Show(info);
            }
    
    public class BindingDataProperyty : INotifyPropertyChanged
        {
    
         ...//使用前面的代码
    
            #region Data Property
            private string Data_ = "";
            public string Data_pro
            {
                get
                {
                    return Data_;
                }
                set
                {
    
                    if (value == Data_)
                    {
                        return;
                    }
                    Data_ = value;
                    NotifyPropertyChanged(() => Data_pro);
                }
            }
            #endregion
    
           ...//使用前面的代码
        }


  • 相关阅读:
    框架_爬虫如何应用(爬虫架构设计与实现)
    架构师_设计模式_结构型_代理模式
    7语法基础_CLR核心解析
    架构师_设计模式_结构型_享元模式
    架构师_设计模式_结构型_组合模式
    同源策略、跨域、Same-origin、Cross-origin
    ES(elasticsearch) query DSL 查询语法
    日志框架
    powerdesigner 名称、注释互转
    maven 可运行 jar 包的打包,包含依赖 jar 包
  • 原文地址:https://www.cnblogs.com/sparkleDai/p/7605065.html
Copyright © 2020-2023  润新知