程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WPF Bug清單之(2)——RadioButton的IsChecked綁定失效

WPF Bug清單之(2)——RadioButton的IsChecked綁定失效

編輯:關於.NET

.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  /**//// <summary>
7  ///
8  /// </summary>
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    /**//// <summary>
21    ///
22    /// </summary>
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    /**//// <summary>
37    ///
38    /// </summary>
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    /**//// <summary>
57    ///
58    /// </summary>
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

1<Window x:Class="BindingRadioButton.DemoWindow"
2  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4  xmlns:model="clr-namespace:BindingRadioButton.Model"
5  Title="RadioButton Binding Lost"
6  Height="300" Width="300">
7  <Window.Resources>
8    <model:Person x:Key="First" Name="Bill Gates"/>
9    <model:Person x:Key="Second" Name="Steve Ballmer"/>
10  </Window.Resources>
11  <DockPanel Margin="12">
12    <GroupBox DockPanel.Dock="Top"
13         Header="Select a CEO for MSFT"
14         Padding="9" Margin="0,0,0,12">
15      <StackPanel>
16        <RadioButton DataContext="{StaticResource First}"
17               IsChecked="{Binding IsCeo}"
18               Content="{Binding Name}"
19               GroupName="ceo" Margin="0,0,0,5"/>
20        <RadioButton DataContext="{StaticResource Second}"
21               IsChecked="{Binding IsCeo}"
22               Content="{Binding Name}"
23               GroupName="ceo"/>
24      </StackPanel>
25    </GroupBox>
26
27    <Label DockPanel.Dock="Top" Content="Message:"
28        Padding="0" Margin="0,0,0,5"/>
29    <TextBox Name="messageBox"/>
30  </DockPanel>
31</Window>

其中的messageBox用於顯示Trace輸出的消息。運行結果如下。

圖1. 剛啟動

現在MSFT沒有CEO,我們點Steve Ballmer選擇一個之後如圖2。

圖2. 選擇一個

然後選擇另一個作為CEO,之後如圖3。

圖3. 選擇另一個

有心的讀者應該已經可以看出,到這裡已經可以證明有一個綁定已經失效了。不過我們繼續用更明顯的方式繼續點點。

再選回Steve Ballmer,如圖4。

圖4. 再選擇一個

結果再沒有消息出來了。很明顯,Binding失效了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved