快捷搜索:

[WPF Bug清单]之(2)——RadioButton的IsChecked绑定失

.NET Framework已经算是一个很易用的库了。可以自动地为我们做很多工作,而且大年夜都做得还不错。然则自动完成的工作很可能会有隐患,由于Framework本身是并不懂得营业逻辑的。它自动完成的工作,可能会给我们帮倒忙。

RadioButton便是此中一个。

先来从设置值的角度先容一下WPF里的Dependency Property(以下简称DP)。在WPF里节制一个控件的DP,有太多的要领。可以用Style,可以用Animation,可以用Data Binding,可以用Trigger,还有最基础直接赋值。控件会综合上面各个方面的值,其及优先级等因向来抉择一个DP的终极的值是若干。关于这方面的更多的常识可以参考雨痕关于DP的文章或MSDN。(不过不确定MSDN上有没有有关DP设值优先级的系统的先容哦。)

多半的控件不会自动的变动自己的某个属性的值。然则总有一些例外。RadioButton便是此中一个。它自动设置什么值了?谜底是IsChecked属性。RadioButton的特征是一组RadioButton只有一个当选中。当一个RadioButton当选中的时刻,其它所有的RadioButton就会被自动地设置IsChecked属性为False。

问题来了,设置一个属性的措施那么多,它自己自动设置这个属性的时刻,应该用什么措施呢?这个问题早在.NET 3.0时就已经有人发明,并在微软的论坛上评论争论过。MSFT的Sam Bent也承认了这个Bug的存在。但问题就在于,无论RadioButton用哪种现有的措施去使得IsChecked属性为False,“总会有些人不痛快”。3.0里RadioButton的自动,会让Style和Template的值掉效;在3.5中,Fix了3.0中的这个Bug,然则却导致Binding掉效。

颠末笔者验证,在.NET 3.5 SP1中应用了与3.5相同的逻辑,纵然Binding掉效。下面我们将用一个“为微软选CEO”的示例法度榜样进行验证。

首先定义一个Person类,如下:

Person

1using System.ComponentModel;

2using System.Diagnostics;

3

4namespace BindingRadioButton.Model

5{

6  /**////

7  ///

8  ///

9  public class Person : INotifyPropertyChanged

10  {

11    Private Fields#region Private Fields

12

13    private bool isCeo;

14    private string name;

15

16    #endregion

17

18    Public Properties#region Public Properties

19

20    /**////

21    ///

22    ///

23    public bool IsCeo

24    {

25      get { return isCeo; }

26      set

27      {

28        if (value != isCeo)

29        {

30          isCeo = value;

31          OnPropertyChanged("IsCeo");

32        }

33      }

34    }

35

36    /**////

37    ///

38    ///

39    public string Name

40    {

41      get { return name; }

42      set

43      {

44        if (value != name)

45        {

46          name = value;

47          OnPropertyChanged("Name");

48        }

49      }

50    }

51

52    #endregion

53

54    INotifyPropertyChanged Members#region INotifyPropertyChanged Members

55

56    /**////

57    ///

58    ///

59    public event PropertyChangedEventHandler PropertyChanged;

60

61    #endregion

62

63    protected virtual void OnPropertyChanged(string propertyName)

64    {

65      PropertyChangedEventHandler temp = PropertyChanged;

66      if (temp != null)

67      {

68        temp(this, new PropertyChangedEventArgs(propertyName));

69        Trace.WriteLine(string.Format("{0} {1} CEOn", Name, IsCeo ? "is" : "is not"));

70      }

71    }

72  }

73}

74

因为实现了INotifyPropertyChanged接口,这个类的实例可以被Binding。我们在PropertyChanged的时刻,输出一条信息,阐明当前的CEO是谁。留意里面IsCeo为False的时刻也会输出消息哦。阐明谁被夺职了。

然后建立UI如下。

UI

1Window x:Class="BindingRadioButton.DemoWindow"

2xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

3xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

4xmlns:model="clr-namespace:BindingRadioButton.Model"

5Title="RadioButton Binding Lost"

6Height="300" Width="300">

7Window.Resources>

8model:Person x:Key="First" Name="Bill Gates"/>

9model:Person x:Key="Second" Name="Steve Ballmer"/>

10Window.Resources>

11DockPanel Margin="12">

12GroupBox DockPanel.Dock="Top"

13Header="Select a CEO for MSFT"

14Padding="9" Margin="0,0,0,12">

15StackPanel>

16RadioButton DataContext="{StaticResource First}"

17IsChecked="{Binding IsCeo}"

18Content="{Binding Name}"

19GroupName="ceo" Margin="0,0,0,5"/>

20RadioButton DataContext="{StaticResource Second}"

21IsChecked="{Binding IsCeo}"

22Content="{Binding Name}"

23GroupName="ceo"/>

24StackPanel>

25GroupBox>

26

27Label DockPanel.Dock="Top" Content="Message:"

28Padding="0" Margin="0,0,0,5"/>

29TextBox Name="messageBox"/>

30DockPanel>

31Window>

您可能还会对下面的文章感兴趣: