Silverlight 2 Customized Control 开发
Customized Control 和 User Control
相信大家比較熟悉使用Silverlight的User Control,在VS2008的Silverlight插件中,可以通過添加新項(Add new Item)創建一個User Control,而且Silverlight在網頁中嵌入的本身就是一個User Control。
本文中講的是如何開發Customized Control,Customized Control是與User Control完全不同的,Customized Control是繼承或者間接繼承System.Windows.Controls.Control的,而User Control必須繼承System.Windows.Controls.Control.UserControl。Customized Control更接近于Silverlight本身提供的Button、CheckBox等Control, User Control則比較類似這些原生Control的組合體。
準備工作
在閱讀本文之前至少應該掌握:
- 創建和使用簡單Silverlight程序
- 使用和編輯Silverlight控件模板
- 使用Silverlight的Visual State
- C#基本知識
- 使用Visual studio的項目和解決方案
推薦鏈接
- http://msdn.microsoft.com/zh-cn/magazine/cc721611.aspx?
一篇for SL2 beta 2的自定義控件開發介紹,有些地方需要變動才能正常工作 - http://silverlight.net/GetStarted/?
官方的Silverlight入門, 其中有SL組成員blog的鏈接 - http://msdn.microsoft.com/en-us/library/cc278068(VS.95).aspx?
MSDN的Control Customization介紹 - http://msdn.microsoft.com/en-us/library/cc838194(VS.95).aspx?
MSDN的Silverlight類庫參考
環境
- Visual Studio 2008 with Service Pack 1
- Silverlight Tools for Visual Studio 2008 SP1
- [optional]Expression Blend 2 with Service Pack 1
(提示:連接給出的默認是英文,大家可以根據習慣選擇。開發工具和Service Pack語言必須對應。)
(注意:Visual Studio和Expression Blend不是免費工具,這里給出的是試用版本鏈接,用于商業開發可能存在風險。)
?
接下來我們可以開始Customized Control之旅了。
(因為不想在基礎的地方浪費時間,所以前面部分會非常簡略,請參考推薦鏈接)
?
一、創建解決方案
Customized Control一般會編寫成DLL文件,所以創建工程的時候應該選擇Silverlight Class Library,同時為了調試,我們還要在解決方案中再建立一個新的Silverlight Application project。如果希望用Web站點來調試Silverlight Application,就還需要創建解決方案中的第三個project,推薦使用動態生成的HTML。然后需要在解決放案屬性中定義好項目的依賴關系以及start up project。考慮到這部分大家都比較了解,就不再贅述。
二、創建Control的C#類
創建的Silverlight Class Library中默認會有一個Class1.cs,這是一個普通的C#類,與Silverlight并無關系,可以選擇保留它利用VS的重構功能換成喜歡的名字,也可以刪掉它再重新建立一個類。總之我們的Class Library中只需要保留一個我們要開發的控件名字的類就可以了,比如我打算開發一個MenuItem。然后我們要繼承Control類,當然也可以繼承任何其它繼承了Control的類。最后代碼看起來像是這樣:
????public?class?MenuItem?:?Control????{
????????public?MenuItem()
????????{
????????}
????}
?
OK,這樣我們就制作出了一個最基本的Customized Control。
三、調用Control
接下來我們希望在Silverlight Application中調用生成的Customized Control,首先要添加引用,因為現在在同一Solution中,所以可以選擇項目引用。
然后我們要把我們類庫的clr命名空間加入到XAML的命名空間當中,所以修改Page.xaml的UserControl為:
?
<UserControl?x:Class="SilverlightMenuTest.Page"????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????xmlns:custom="clr-namespace:SilverlightMenu;assembly=SilverlightMenu"
????Width="400"?Height="300"?/>
?
?
clr-namespace寫我們類庫中使用的namespace,assembly寫類庫項目的名稱就可以了,XML命名空間可以是我們喜歡的任何名字,這里用了custom。
然后我們可以在XAML中使用我們的新控件了,控件名稱和C#類名相同,前面要帶上命名空間,代碼最后類似這樣:
<UserControl?x:Class="SilverlightMenuTest.Page"????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????xmlns:custom="clr-namespace:SilverlightMenu;assembly=SilverlightMenu"
????Width="400"?Height="300">
????<Grid?x:Name="LayoutRoot"?Background="White">
????????<custom:MenuItem?/>
????</Grid>
</UserControl>
接下來我們可以運行程序了,但是當然結果是一片空白。
四、添加模板
這個一片空白的Control顯然沒有任何意義,接下來我們要讓它變成可見的。只需要設置好MenuItem的Template屬性就可以了,可以看到這里設置了Width和Height,Template中的元素會自動把自己限制在這個范圍內。
<UserControl?x:Class="SilverlightMenuTest.Page"????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????xmlns:custom="clr-namespace:SilverlightMenu;assembly=SilverlightMenu"
????Width="400"?Height="300">
????<Grid?x:Name="LayoutRoot"?Background="White"?Width="100"?Height="24">
????????<custom:MenuItem>
????????????<custom:MenuItem.Template>
????????????????<ControlTemplate>
????????????????????<Rectangle?Fill="Black"?StrokeThickness="1"?RadiusX="2"?RadiusY="2"?x:Name="Bg"/>
????????????????</ControlTemplate>
????????????</custom:MenuItem.Template>
????????</custom:MenuItem>
????</Grid>
</UserControl> 顯示這段代碼我們就可以看到一個黑色的圓角矩形了。
五、綁定屬性
這樣我們有了一個可見的控件,但是這個控件的任何屬性(如Background之類的)都沒有辦法發生作用。現在我們可以想想辦法讓矩形的顏色是控件的背景色。使用Silverlight的屬性文法,可以將矩形的Fill屬性綁定到MenuItem控件的Background。
<UserControl?x:Class="SilverlightMenuTest.Page"????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????xmlns:custom="clr-namespace:SilverlightMenu;assembly=SilverlightMenu"
????Width="400"?Height="300">
????<Grid?x:Name="LayoutRoot"?Background="White"?Width="100"?Height="24">
????????<custom:MenuItem?Background="Blue"?>
????????????<custom:MenuItem.Template>
????????????????<ControlTemplate>
????????????????????<Rectangle?Fill="{TemplateBinding?Background}"?StrokeThickness="1"?RadiusX="2"?RadiusY="2"?x:Name="Bg"/>
????????????????</ControlTemplate>
????????????</custom:MenuItem.Template>
????????</custom:MenuItem>
????</Grid>
</UserControl>
感興趣的話,可以試著把Rectangle的Stroke綁定到MenuItem的BorderBrush。這樣,我們就可以通過控件的屬性控制控件的顯示效果了。
六、添加默認模板
當然你不能要求使用者總是編輯你的Control的模板,所以我們必須要有一個默認的模板。VisualStudio總是會從項目的themes文件夾下查找generic.xaml作為默認模板,注意這個項目是控件的類所在的項目,也就是我們建立的Silverlight Class Library。
如果你看過之前的介紹Silverlight自定義控件開發的文章,你會發現,這個地方Silverlight 2 RTW版和Silverlight 2 beta 2或者beta 1是不兼容的,我們必須將generic.xaml放到themes目錄下。beta 2版本是放在根目錄下,而beta 1版本是放在根目錄下且必須修改generic.xaml的屬性才能生效。
一個空的generic.xaml的內容如下(但是VS不會自動為你生成這個文件,需要手動添加):
<ResourceDictionary????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</ResourceDictionary>
我們需要通過style把新控件的模板放進去,但之前應該先把clr命名空間加入。
<ResourceDictionary????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????xmlns:custom="clr-namespace:SilverlightMenu;assembly=SilverlightMenu">
</ResourceDictionary>
最后的XAML類似這樣(style大家并不陌生,就不多講了)
?
<ResourceDictionary????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????xmlns:custom="clr-namespace:SilverlightMenu;assembly=SilverlightMenu">
????<Style?TargetType="custom:MenuItem">
????????<Setter?Property="Template">
????????????<Setter.Value>
????????????????<ControlTemplate?TargetType="custom:MenuItem">
????????????????????<Rectangle?Fill="{TemplateBinding?Background}"?StrokeThickness="1"?RadiusX="2"?RadiusY="2"?x:Name="Bg"/>
????????????????</ControlTemplate>
????????????</Setter.Value>
????????</Setter>
????</Style>
</ResourceDictionary>
?
但僅僅如此控件是不會有任何變化的,要在MenuItem的構造函數中加入一句:
this.DefaultStyleKey?=?typeof(MenuItem); 這樣我們的Control就更接近原生Control了,可以這樣調用: <UserControl?x:Class="SilverlightMenuTest.Page"????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????xmlns:custom="clr-namespace:SilverlightMenu;assembly=SilverlightMenu"
????Width="400"?Height="300">
????<Grid?x:Name="LayoutRoot"?Background="White"?Width="100"?Height="24">
????????<custom:MenuItem?Background="Black"></custom:MenuItem>
????</Grid>
</UserControl>
再運行就可以看到黑色矩形了。
七、綁定事件
到此為止,我們的Control還只能是顯示出來看看,沒有任何交互性,下面我們就來給它添加一定的交互性。因為Control本身提供了一些事件,所以我們很容易捕獲這些事件并作出響應。對于Control來說,我們只需要添加事件處理函數并且綁定到相應事件就可以了。
namespace?System.Windows.Controls{
????public?class?MenuItem?:?Control
????{
????????public?MenuItem()
????????{
????????????this.DefaultStyleKey?=?typeof(MenuItem);
????????????this.MouseEnter?+=?new?MouseEventHandler(OnMouseEnter);
????????}
????????public?void?OnMouseEnter(object?sender,?MouseEventArgs?args)
????????{
????????}
????}
} 可以在OnMouseEnter中設置斷點來觀察事件響應情況。
八、操作模板成員
現在我們知道了如何通過事件處理函數響應事件,我們可以在其中改變控件自身的狀態,比如,當鼠標劃過時,改變控件的背景。前面說到背景顯示是通過一個Rectangle實現的,那么要改變背景就需要取到這個Rectangle,我們要使用一個函數GetTemplateChild來取這個元素。注意因為GetTemplateChild并不一定總能取到元素,而且元素類型并不一定是我們期望的(了解Template的朋友會知道,Template是一個可以被EndUser修改的屬性,所以不能以任何形式斷言控件Template的結構和其中的元素名),所以一定要處理異常。下面的代碼是讓鼠標在控件上時背景變成紅色:
public?class?MenuItem?:?Control{
????public?MenuItem()
????{
????????this.DefaultStyleKey?=?typeof(MenuItem);
????????this.MouseEnter?+=?new?MouseEventHandler(OnMouseEnter);
????????this.MouseLeave?+=?new?MouseEventHandler(OnMouseLeave);
????}
????public?void?OnMouseEnter(object?sender,?MouseEventArgs?args)
????{
????????try
????????{
????????????Rectangle?BgRect?=?GetTemplateChild("Bg")?as?Rectangle;
????????????BgRect.Fill?=?new?SolidColorBrush(Color.FromArgb(255,?255,?0,?0));
????????}
????????catch
????????{
????????}
????}
????public?void?OnMouseLeave(object?sender,?MouseEventArgs?args)
????{
????????try
????????{
????????????Rectangle?BgRect?=?GetTemplateChild("Bg")?as?Rectangle;
????????????BgRect.Fill?=?new?SolidColorBrush(Color.FromArgb(255,?0,?0,?0));
????????}
????????catch
????????{
????????}
????}
} 有些時候,我們希望在模板生效的時候就對某些模板成員進行操作,如綁定事件,調整屬性等,就需要一個事件OnApplyTemplate,我們只能通過override父類的OnApplyTemplate來響應模板生效事件:
?
九、添加可視狀態(VisualState)
上面的代碼實現了我們想要的功能,然而卻有很多問題:
那么如何解決呢?很顯然,跟使用Silverlight開發Web應用一樣,答案就是使用VisualState。首先我們要為我們的控件模板定義VisualState,因為VisualState必須定義在root element上,所以這里我稍微做了一點改動,給模板加了一個容器。關于如何定義和使用VisualState,早有不少高手寫的很清楚,這里就不再重復了。下面的Visual定義了2個互斥的狀態MouseOver和MouseOut,MouseOver狀態將背景Rectangle顏色變紅,MouseOut則恢復原狀。
<ResourceDictionary????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
????xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
????xmlns:custom="clr-namespace:System.Windows.Controls;assembly=SilverlightMenu">
????<Style?TargetType="custom:MenuItem">
????????<Setter?Property="Template">
????????????<Setter.Value>
????????????????<ControlTemplate?TargetType="custom:MenuItem">
????????????????????<Grid>
????????????????????????<vsm:VisualStateManager.VisualStateGroups>
????????????????????????????<vsm:VisualStateGroup?x:Name="MouseOverStates">
????????????????????????????????<vsm:VisualState?x:Name="MouseOver">
????????????????????????????????????<Storyboard>
????????????????????????????????????????<ObjectAnimationUsingKeyFrames?Storyboard.TargetName="Bg"?Storyboard.TargetProperty="Fill"?Duration="0:0:0">
????????????????????????????????????????????<ObjectAnimationUsingKeyFrames.KeyFrames>
????????????????????????????????????????????????<DiscreteObjectKeyFrame?KeyTime="0:0:0">
????????????????????????????????????????????????????<DiscreteObjectKeyFrame.Value>
????????????????????????????????????????????????????????<SolidColorBrush?Color="#FFFF0000"></SolidColorBrush>
????????????????????????????????????????????????????</DiscreteObjectKeyFrame.Value>
????????????????????????????????????????????????</DiscreteObjectKeyFrame>
????????????????????????????????????????????</ObjectAnimationUsingKeyFrames.KeyFrames>
????????????????????????????????????????</ObjectAnimationUsingKeyFrames>
????????????????????????????????????</Storyboard>
????????????????????????????????</vsm:VisualState>
????????????????????????????????<vsm:VisualState?x:Name="MouseOut">
????????????????????????????????????<Storyboard>
????????????????????????????????????</Storyboard>
????????????????????????????????</vsm:VisualState>
????????????????????????????</vsm:VisualStateGroup>
????????????????????????</vsm:VisualStateManager.VisualStateGroups>
????????????????????????<Rectangle?Fill="{TemplateBinding?Background}"?StrokeThickness="1"?RadiusX="2"?RadiusY="2"?x:Name="Bg"/>
????????????????????</Grid>
????????????????</ControlTemplate>
????????????</Setter.Value>
????????</Setter>
????</Style>
</ResourceDictionary>
定義好了Visual State,我們的事件就可以寫的很簡單了:
public?class?MenuItem?:?Control{
????public?MenuItem()
????{
????????this.DefaultStyleKey?=?typeof(MenuItem);
????????this.MouseEnter?+=?new?MouseEventHandler(OnMouseEnter);
????????this.MouseLeave?+=?new?MouseEventHandler(OnMouseLeave);
????}
????public?void?OnMouseEnter(object?sender,?MouseEventArgs?args)
????{
????????VisualStateManager.GoToState(this,?"MouseOver",?false);
????}
????public?void?OnMouseLeave(object?sender,?MouseEventArgs?args)
????{
????????VisualStateManager.GoToState(this,?"MouseOut",?false);
????}
} 這樣運行下試試看,是不是很cool?
?
十、添加自定義屬性
接下來到了最后的部分了,也是最少資料涉及的部分,Silverlight Customized Control自定義屬性。下面我們來以一個Text屬性為例演示如何創建一個自定義屬性,這個例子將會用到一些前面的內容。首先我們要為DependencyObject的屬性聲明一個公有的DependencyProperty,這個屬性是靜態的,可以用于數據綁定。(還記得數據綁定中使用的DependencyProperty吧,就是這樣的哦^^)
?
????public?static?readonly?DependencyProperty?TextProperty;?
靜態屬性在靜態構造函數中初始化,這里有一點復雜,首先看完整代碼:
????static?MenuItem()????{
????????TextProperty?=?DependencyProperty.Register("Text",?typeof(string),?typeof(MenuItem),?new?PropertyMetadata(false,?new?PropertyChangedCallback(MenuItem.OnTextPropertyChanged)));
????} DependencyProperty應該由DependencyProperty.Register創建,在MSDN中,這個函數的原型如下: public?static?DependencyProperty?Register(
????string?name,
????Type?propertyType,
????Type?ownerType,
????PropertyMetadata?typeMetadata
) ?
其中name是屬性在XAML中使用的名字,propertyType則是屬性的類型,注意這個屬性理論上可以是任何類型,但是一般只使用整數、布爾、字符串、還有UI元素這些類型,其它類型需要定義復雜的字符串到對象的屬性文法作為轉換規則(之后可能會單寫一篇blog講converter)。ownerType就是我們自己定義的類了。typeMetadata有點復雜,PropertyMetadata構造函數有3個重載,提供選擇指定defaultValue和propertyChangedCallback中任意一個或者同時指定2個。原型如下:
public?PropertyMetadata(????Object?defaultValue,
????PropertyChangedCallback?propertyChangedCallback
)
?
defaultValue是屬性的默認值沒什么可說,propertyChangedCallback也很簡單,就是當屬性改變時的處理函數,這個是把屬性同我們的類聯系起來的關鍵了,PropertyChangedCallback 是個委托類型,它的簽名也可以在MSDN查到:
public?delegate?void?PropertyChangedCallback(????DependencyObject?d,
????DependencyPropertyChangedEventArgs?e
)
為了理解這個函數,我們可以先看一下我對Text屬性的實現:
????private?static?void?OnTextPropertyChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e)????{
????????(d?as?MenuItem).OnTextPropertyChanged(e);
????}
????void?OnTextPropertyChanged(DependencyPropertyChangedEventArgs?e)
????{
????????try
????????{
????????????(GetTemplateChild("TB")?as?TextBlock).Text?=?e.NewValue?as?string;
????????}
????????catch
????????{
????????}
????} 其實可以在static的OnTextPropertyChanged里面直接操作也是可以的,這個實現結構比較合理。可以看到,這個PropertyChangedCallback參數中,d就是屬性所在的對象,而e則是屬性改變時的信息,包括NewValue,OldValue等等,通常我們關心的是NewValue。
之后,我們要給我們的對象添加一個相應的C#屬性,這個屬性一定要和XAML里的屬性名字完全一致,因為DependencyObject會用反射來訪問這個屬性。這個屬性的getter和setter中不應該有多余的內容,應該只是簡單的轉發操作到DependencyObject,所以看起來就像下面這樣:???????
????public?string?Text????{
????????get
????????{
????????????return?(string)base.GetValue(TextProperty);
????????}
????????set
????????{
????????????base.SetValue(TextProperty,?value);
????????}
????} 然后我們還需要設置模板內容,把TextBlock加入。generic.xaml最終版如下:
?
<ResourceDictionary????????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"????
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"????
????xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"????
????xmlns:custom="clr-namespace:System.Windows.Controls;assembly=SilverlightMenu">
????<Style?TargetType="custom:MenuItem">
????????<Setter?Property="Template">
????????????<Setter.Value>
????????????????<ControlTemplate?TargetType="custom:MenuItem">
????????????????????<Grid>
????????????????????????<vsm:VisualStateManager.VisualStateGroups>
????????????????????????????<vsm:VisualStateGroup?x:Name="MouseOverStates">
????????????????????????????????<vsm:VisualState?x:Name="MouseOver">
????????????????????????????????????<Storyboard>
????????????????????????????????????????<ObjectAnimationUsingKeyFrames?Storyboard.TargetName="Bg"?Storyboard.TargetProperty="Fill"?Duration="0:0:0">
????????????????????????????????????????????<ObjectAnimationUsingKeyFrames.KeyFrames>
????????????????????????????????????????????????<DiscreteObjectKeyFrame?KeyTime="0:0:0">
????????????????????????????????????????????????????<DiscreteObjectKeyFrame.Value>
????????????????????????????????????????????????????????<SolidColorBrush?Color="#FFFF0000"></SolidColorBrush>
????????????????????????????????????????????????????</DiscreteObjectKeyFrame.Value>
????????????????????????????????????????????????</DiscreteObjectKeyFrame>
????????????????????????????????????????????</ObjectAnimationUsingKeyFrames.KeyFrames>
????????????????????????????????????????</ObjectAnimationUsingKeyFrames>
????????????????????????????????????</Storyboard>
????????????????????????????????</vsm:VisualState>
????????????????????????????????<vsm:VisualState?x:Name="MouseOut">
????????????????????????????????????<Storyboard></Storyboard>
????????????????????????????????</vsm:VisualState>
????????????????????????????</vsm:VisualStateGroup>
????????????????????????</vsm:VisualStateManager.VisualStateGroups>
????????????????????????<Rectangle?Fill="{TemplateBinding?Background}"?StrokeThickness="1"?RadiusX="2"?RadiusY="2"?x:Name="Bg"/>
????????????????????????<TextBlock?x:Name="TB"></TextBlock>
????????????????????</Grid>
????????????????</ControlTemplate>
????????????</Setter.Value>
????????</Setter>
????</Style>
</ResourceDictionary>?
這樣看起來就基本完成了,然而,在測試代碼里加入這個屬性之后,卻得不到我們想要的結果。
<UserControl?x:Class="SilverlightMenuTest.Page"????????xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"????
????xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"????
????xmlns:custom="clr-namespace:System.Windows.Controls;assembly=SilverlightMenu"????
????Width="400"?Height="300">
????<Grid?x:Name="LayoutRoot"?Background="White"?Width="400"?Height="300">
????????<custom:MenuItem?Text="Hello"?Background="Black"?Width="100"?Height="24"></custom:MenuItem>
????</Grid>
</UserControl>
為什么呢,注意到,我們在屬性變化的時候直接GetTemplateChild,并沒有考慮到這時TextBlock是否已經創建,在SL中,Text屬性設置其實是發生在Template生效之前的,所以設置Text的時候取不到TB元素。那么,我們就需要考慮在加載模板完成的時候,取出Text屬性并且設置到TB上。
如上文所述,我們override OnApplyTemplate來獲取想要的結果,最終版的MenuItem.cs代碼:
?
using?System;using?System.Net;
using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Documents;
using?System.Windows.Ink;
using?System.Windows.Input;
using?System.Windows.Media;
using?System.Windows.Media.Animation;
using?System.Windows.Shapes;
using?System.ComponentModel;
namespace?System.Windows.Controls
{
????public?class?MenuItem?:?Control
????{
????????public?static?readonly?DependencyProperty?TextProperty;
????????static?MenuItem()
????????{
????????????TextProperty?=?DependencyProperty.Register("Text",?typeof(string),?typeof(MenuItem),?new?PropertyMetadata("",?new?PropertyChangedCallback(MenuItem.OnTextPropertyChanged)));
????????}
????????private?static?void?OnTextPropertyChanged(DependencyObject?d,?DependencyPropertyChangedEventArgs?e)
????????{
????????????(d?as?MenuItem).OnTextPropertyChanged(e);
????????}
????????void?OnTextPropertyChanged(DependencyPropertyChangedEventArgs?e)
????????{
????????????try
????????????{
????????????????(GetTemplateChild("TB")?as?TextBlock).Text?=?e.NewValue?as?string;
????????????}
????????????catch
????????????{?}
????????}
????????public?string?Text
????????{
????????????get
????????????{
????????????????return?(string)base.GetValue(TextProperty);
????????????}
????????????set
????????????{
????????????????base.SetValue(TextProperty,?value);
????????????}
????????}
????????public?MenuItem()
????????{
????????????this.DefaultStyleKey?=?typeof(MenuItem);
????????????this.MouseEnter?+=?new?MouseEventHandler(OnMouseEnter);
????????????this.MouseLeave?+=?new?MouseEventHandler(OnMouseLeave);
????????}
????????public?override?void?OnApplyTemplate()
????????{
????????????base.OnApplyTemplate();
????????????try
????????????{
????????????????var?tb?=?GetTemplateChild("TB")?as?TextBlock;
????????????????(GetTemplateChild("TB")?as?TextBlock).Text?=?this.Text;
????????????}
????????????catch
????????????{?}
????????}
????????public?void?OnMouseEnter(object?sender,?MouseEventArgs?args)
????????{
????????????VisualStateManager.GoToState(this,?"MouseOver",?false);
????????}
????????public?void?OnMouseLeave(object?sender,?MouseEventArgs?args)
????????{
????????????VisualStateManager.GoToState(this,?"MouseOut",?false);
????????}
????}
}
寫到這里,我們的自定義Control開發大體流程以及關鍵技術問題就已經比較清楚了,雖然這個MenuItem距離實用還有很遠的距離,各位應該可以自己完成它。感謝讀完本文的你,Enjoy Silverlight Customized Control.
總結
以上是生活随笔為你收集整理的Silverlight 2 Customized Control 开发的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows NT体系结构
- 下一篇: vlan间ACL和VACL的区别