返回首页

简介
本文介绍了控制,支持简化类型之间的RadioButton控制面板和枚举属性的数据绑定。 背景
。NET Windows窗体我曾参与过的项目,piddling的困扰,我比任何其他的问题是缺乏支持RadioButton的处理。当然,你可以粘在一个小组或GroupBox的RadioButtons一堆,将请执行Windows窗体上设置一个最小的分组行为,使选择在任何一个时间只有一个无线电。问题arisesnbsp; younbsp;时需要知道是哪个RadioButton的检查。无论是小组也没有的GroupBox表面会告诉你这一个事件或财产,它留给你的,提供一个单一的RadioButton组中的每一个的事件处理程序。不用说,这个可怜的支持,很容易绑定RadioButton组是前功尽弃,但一个白日梦。
其他人更聪明,比我已经递上了解决这个问题。最好的可能是{A},模拟相应的ASP.NET控件。虽然好,该解决方案达成我严重矫枉过正。我想要的是一个简单的解决方案,使用标准的单选按钮 - 自定义面板控制,提供双向数据绑定到业务对象的枚举类型的属性,以及作为一个单一的事件通知,指示当前选择改变时。我并不需要一个quot; codequot;的做法,必然 - 只是一个方法,大大简化了意大利面条式的代码,不可避免地带来的RadioButton处理。
我的解决方案,RadioPanel,需要最少的布线:极少数的设计师设置,加上一行代码。在应用程序需要两个,三个或更多的RadioButton板,这个法术在代码中的相当大的减少。使用代码
图1显示了简单的业务对象代表的船只。我们的船有一个Type属性,标志着由VesselType枚举:

public enum VesselType

{

    Cargo = 0,

    Container,

    BulkCarrier,

    Reefer,

    Passenger,

    Tanker

} 

我们可以使用RadioPanel面板包含这些选项的每一个按钮创建一个新形式。拉断我们的约束力,我们利用的事实,在Windows Forms 2.0中的每一个控件公开一个标签属性接受任意数据。每个RadioButton填充其相应的选项,在我们的VesselType枚举数值,我们将使用Tag属性。由于"Cargoquot; VesselType在第一个选项,我们分配rbVesselTypeCargo.Tag值为0。接着,我们rbVesselTypeContainer.Tag = 1,所以我们所有的RadioButton选项。
RadioPanel支持名为ValueMember一个属性,表明我们希望绑定到的属性。我们给这个价值的quot; Type.quot;最后,我们窗体的Load事件里面,我们创建我们的业务对象的一个​​实例,并分配到DataSource属性的RadioPanel:{C}
,您可以运行此应用程序,并使用调试器来验证Vessel.Type财产更新,当您选择一个新的类型船只。您可以使用",设定Valuequot按钮的形式,以验证绑定是双向的:当船舶更新对象,所以是RadioButton的选择。兴趣点
的代码,驾驶这使得相当简单使用。NET的功能强大的反射API。反射使您能够在运行时对象的属性,方法和事件。这是被称为后期绑定,而不是在编译过程中执行的早期绑定:而不是在代码中指定你的属性和方法调用静态,你可以获取一个通用的参考的对象,并调用其属性和方法,使用字符串参数。RadioPanel踢关闭程序,一旦检测到您已分配有效的ValueMember和DataSource属性。 DataSource属性使用Object.GetType()来获取数据源的基础类型的引用。然后,它采用Type.GetInterface()方法来发现我们的数据源是否支持INotifyPropertyChanged的。如果是这样,它使用Type.GetEvent()得到一个PropertyChanged事件的处理,并建立了一个侦听器。
Type iface = _dataSource.GetType().GetInterface("INotifyPropertyChanged");



if (iface != null)

{

    _ei = iface.GetEvent("PropertyChanged");



    if (_ei != null) // which would be weird if it did...

    {

        _ei.AddEventHandler(_dataSource, _pceh);

    }

}

取得ValueMember属性收益以类似的方式值的代码。 Type.GetProperty()方法返回PropertyInfo类型的对象,它支持读取和使用GetValue的基本财产的价值()的SetValue()方法,分别设置。这是相当简单的代码,所以我不会在这里重现;看到完整的项目细节。
我们怎么知道什么时候选择一个RadioButton已经改变?很简单:我们一直在倾听每个RadioButton的CheckedChanged事件,我们作为我们的切入点事件接线面板中的父ControlAdded方法:
protected override void OnControlAdded(ControlEventArgs e)

{

    base.OnControlAdded(e);



    if (e.Control is RadioButton)

    {

        RadioButton rb = (RadioButton)e.Control;

        rb.CheckedChanged += rb_CheckedChanged;

    }

}

rb_CheckedChanged然后射击RadioButtonSelectionChanged事件,以及我们的DataSource设置新选定的值。注意,我们使用一个布尔标志,以防止反射代码,这将产生处理PropertyChanged的通知。也许最"; magicalquot;这个代码的一部分,是Enum.Parse()调用,RadioButton.Tag VesselType枚举的一个实例中发现的整数转换。
void rb_CheckedChanged(object sender, EventArgs e)

{ 

    if (_dataSource != null)

    {

        int nSetting = 0;



        if (sender is RadioButton)

        {

            RadioButton rbSender = (RadioButton)sender;



            // Fire the RadioButtonChanged event.

            FireRadioSelectionChanged(rbSender);



            if (rbSender.Tag == null)

            {

                throw new InvalidOperationException("RadioButton " + rbSender.Name + 

                 " does not have its Tag property set to a valid enum integer value.");

            }



            if (!Int32.TryParse(rbSender.Tag.ToString(), out nSetting))

            {

                throw new InvalidOperationException("RadioButton " + rbSender.Name +

                   " does not have its Tag property set to a valid enum integer value.");

            }



            PropertyInfo pi = 

		(PropertyInfo)_dataSource.GetType().GetProperty(_valueMember);

            if (pi != null)

            {

                // Convert the int into its corresponding enum. 

	       // pi.PropertyType represents the enum's type.

                object parsedEnum;

                try

                {

                    parsedEnum = Enum.Parse(pi.PropertyType, nSetting.ToString());

                }

                catch (Exception ex)

                {

                    throw new InvalidOperationException

		   ("Could not convert RadioButton.Tag value into an enum.", ex);

                }



                // Stop listening to property changes while we change the property

	       //  - otherwise, stack overflow.

                _processPropertyChange = false;



                pi.SetValue(_dataSource, parsedEnum, null);



                _processPropertyChange = true;

            }

        }

    }

} 

对于大多数用途,但是,你会不会担心这quot;下curtainquot,布线,只需添加到您的控制库的控制,并用它来你的心脏的内容。我想你会发现它很好地收拾你的Windows窗体界面代码。历史2007年8月28日:战后初期

回答

评论会员:igetorix 时间:2011/12/15
非常有帮助。感谢
评论会员:游客 时间:2011/12/15
|周杰伦,你的控制很好地解决了我在我application.nbsp的问题之一;Arkitec:然而,在阅读您的文章您radiopanel称为一个radiopanelbutton,而不是使用单选按钮tag.nbsp!;下面是一个用户控件基础上的单选按钮。对不起,我只注意到原有的控制是在C#-我翻译成VB的我自己的应用程序,但你的idea.nbsp;进口System.ComponentModel命名空间控制''"AMP;LT;summaryamp;GT;NBSP""单选按钮控制用于RadioPanel控制'''放大器;/summaryamp;GT;公共类RadioPanelButtonBR}私人_value可为空(整数)"AMP;LT;summaryamp;GT;'''获取或设置此RadioButton的值。NBSP;-;'''放大器;/summaryamp;GT;'''放大器;LT;valueampGT;value.amp;LT;valueamp;GT/放大器;LT;可浏览(TRUE),可绑定(真),描述("要返回的值,如果这个按钮是推"),_类别("行为")放大器;GT;_-;公共属性值可为空(整数)如果_value.HasValue然后-;返回_value.ValueNBSP;-;ELSENBSP-;什么回报-;结束如果最终获取-;设置(BYVAL可为空值(整数))-;_value=值完NBSP;-;高端物业的PublicSubNew()NBSP-;MyBase.New()该调用是Windows窗体设计器所要求的。的InitializeComponent()NBSP-;-;结束小组尾类完命名空间和三在你的面板例程现改为:NBSP分SetRadioButtonValue()NBSP-;如果(_pi为Nothing)NBSP;NBSPNBSP掷新InvalidOperationException异常("_pi可以不被无关。")NBSP结束如果{BR}DIMØ对象=_pi.GetValue(_dataSource,没有){BR}DIM我为Int32=0-;NBSP"为Int32NBSPDIMnSetting;DIMstrInt作为字符串=DirectCast(O,Int32的)的ToString()如果Int32.TryParse(strInt,我)-;对于每个作为对照组的控制NBSPC;-;如果(TypeOf运算彗星RadioPanelButton)NBSP;-;DirectCast(C,RadioPanelButton){BR}NBSP-;如果(价值是什么。)-;抛出新的InvalidOperationException异常("RadioPanelButton"放大器;放大器;名放大器;放大器;-NBSP-;"不会有它的Value属性设置为一个有效的枚举整数值。")NBSP;-;NBSP;结束如果NBSPNBSP-;如果值=I-;"DIMRBRadioPanelButton=DirectCast(C,RadioPanelButton)NBSP-;检查=TRUE-;如果NBSP结束;NBSP-;以NBSP结尾;-;如果NBSP结束;NBSP-;下一步结束如果-;ENDSUB私人小组rb_CheckedChanged(BYVAL发送者为对象,BYVALe视的EventArgs)NBSP,如果没有那么_dataSourceIsNot运算-;NBSP"DIMnSetting为Int32=0-;DIM作为的PropertyInfoNBSPPI-;如果(TypeOf运算发件人RadioPanelButton)NBSP-;DIMrbSenderRadioPanelButton=DirectCast(发件人,RadioPanelButton)NBSP-;rbSender-;"消防RadioButtonChanged事件。NBSP-;FireRadioSelectionChanged(rbSender)-;如果(。价值为Nothing)NBSP;-;投掷新InvalidOperationException异常("RadioPanelButton"放大器;放大器;名放大器;放大器;_-;"没有Tag属性设置一个有效的枚举整数值")。-;结束如果NBSP;-;值=价值PI=DirectCast(_dataSource.GetType()的getProperty(_valueMember)的PropertyInfo)-;如果(PIIsNot运算中的Nothing)-;'int到其相应的枚举的转换。NBSP-;NBSP。"pi.PropertyType代表枚举类型NBSP-;DIMparsedEnum作为对象-;尝试-;-;-;parsedEnum=[枚举]解析(pi.PropertyType,Value.ToString())NBSP。-;赶上异常NBSP前;NBSP;-;NBSP-;掷新InvalidOperationException异常("无法转换成一个枚举RadioPanelButton.Value值。"EX)-;ENDTRYNBSP;-;NBSP,"停止监听属性的变化,而我们改变属性-否则,堆栈溢出NBSP。;-;_processPropertyChange=假NBSP-;pi.SetValue(_dataSource,parsedEnum,为Nothing)-;_processPropertyChange=TRUE-;结束如果NBSP;以NBSP结尾,如果NBSP结束;NBSP-;结束如果ENDSUB-;私人小组的setValue(BYVAL值)对于每个作为对照组的控制NBSPC;如果(TypeOf运算彗星RadioPanelButton)DirectCast(C,RadioPanelButton)NBSP如果(价值是什么。)-;抛出新的InvalidOperationException异常("RadioPanelButton"放大器;放大器;名放大器;放大器;_NBSP;-;NBSP;"没有其Value属性设置为一个有效的枚举整数值。")NBSP;-;结束如果-;如果值=值,NBSP-;检查=TRUE-;-;结束如果NBSP-;以NBSP结尾;-;如果NBSP结束;NBSP-;下一步结束小组
艾哈迈德Shawky齐丹
评论会员:非常感谢你 时间:2011/12/15
edge9421
评论会员:游客 时间:2011/12/15
你文章正是我需要为我的项目。我使用的控件的属性枚举和单选按钮之间的绑定。我的版本不同,我做我的自定义面板揭露单值属性,而不是一个枚举类型的DataSource和DataMember属性,并在面板实现INofifyPropertyChanged。允许我使用直接控制价值之间的财产和我的源对象的属性绑定。在内部,它的工作原理基本相同的,你做了什么。和你一样,我也没有一个风扇的使用上进行协调的单选按钮标签,但我想不出一种方法来改变。我没添加一些额外的"机灵"的标签处理,让号码,姓名和实际的枚举值,以提供更多的选择,在设计或代码(代码可以设置实际的枚举值)设置单选按钮的标签。我觉得不错的设计师枚举的标签上的标签,所以我没有记住的数字NBSP-基思
ndennisv
评论会员:游客 时间:2011/12/15
我很高兴看到这是微软的问题。我花了几个小时,试图找出为什么数据绑定单选按钮不会正确更新。寻找您的文章之前,我试图使用的标签,而数据绑定,但结束了一个真正的混乱。我结束了所有联合国结合我多年的RadioButtons在radioButton_CheckedChanged和使用标记():codepreRadioButtonrb=senderasRadioButton; DataRowdr=DataSet.Customers.Rows[BindingSource.Position];spanclass="code-keyword"if/span(!rb.Checked)dr[rb.Tag.ToString()]=spanclass="code-keyword"false/span;spanclass="code-keyword"else/spandr[rb.Tag.ToString()]=spanclass="code-keyword"true/span;/pre/code当编辑记录和设置单选按钮的时候,我呼吁像这样的列表:codepreMMBOLradioButton.Checked=Convert.ToBoolean(dr[spanclass="code-string""/spanspanclass="code-string"MMBOL"/span]);....../pre/code再次感谢,丹尼斯亚拉巴马州移动,
Sitary
评论会员:游客 时间:2011/12/15
尼斯实施-你有我5。西蒙
周杰伦安德鲁艾伦
评论会员:游客 时间:2011/12/15
西蒙的积极反馈,谢谢!周杰伦安德鲁艾伦http://www.jayandrewallen.com/