有時須要用三張圖片(正常狀態,鼠標移上,鼠標按下)來做爲一個按鈕的樣式,雖然這種作法很差,應該用矢量的方式製做樣式,但有的時候仍是須要這樣作的。html
每次都修改按鈕的樣式來實現這個作法,既麻煩又會生成大段的XAML代碼,不利於維護,抽出一個自定義圖片按鈕控件,只需傳入三張圖片的路徑便可使用,顯然是更好的作法,下面就演示一下如何編寫這個控件,VS2015和Blend2015結合使用。ide
1. 首先,在VS中新建一個WPF自定義控件庫,命名爲WpfCustomControlLibrary,系統會自動生成一個CustomControl1類,並生成一個Themes文件夾,其中包含一個資源字典文件Generic.xaml。若是打開AssemblyInfo.cs文件,會看到包含以下代碼,佈局
[assembly:ThemeInfo( ResourceDictionaryLocation.None, //主題特定資源詞典所處位置 //(在頁面、應用程序或任何主題特定資源詞典中 // 未找到某個資源的狀況下使用) ResourceDictionaryLocation.SourceAssembly //常規資源詞典所處位置 //(在頁面、應用程序或任何主題特定資源詞典中 // 未找到某個資源的狀況下使用) )]
這段代碼指明在Themes文件夾下的Generic.xaml資源字典中包含控件的默認樣式,這正是WPF自定義控件庫和通常程序集的區別。spa
2. 將CustomControl1類改成ImageButtoncode
此時的初始代碼以下,orm
public class ImageButton : Control { static ImageButton() { DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton))); } }
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfCustomControlLibrary"> <Style TargetType="{x:Type local:ImageButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:ImageButton}"> <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}"> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
3. 把ImageButton的基類改成Button。xml
4. 在ImageButton中加入三個依賴屬性,以下htm
public static readonly DependencyProperty NormalImageProperty = DependencyProperty.RegisterAttached("NormalImage", typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(null)); public ImageSource NormalImage { get { return (ImageSource)GetValue(NormalImageProperty); } set { SetValue(NormalImageProperty, value); } } public static readonly DependencyProperty MouseOverImageProperty = DependencyProperty.RegisterAttached("MouseOverImage", typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(null)); public ImageSource MouseOverImage { get { return (ImageSource)GetValue(MouseOverImageProperty); } set { SetValue(MouseOverImageProperty, value); } } public static readonly DependencyProperty PressedImageProperty = DependencyProperty.RegisterAttached("PressedImage", typeof(ImageSource), typeof(ImageButton), new PropertyMetadata(null)); public ImageSource PressedImage { get { return (ImageSource)GetValue(PressedImageProperty); } set { SetValue(PressedImageProperty, value); } }
5. 新建一個WPF應用程序項目引用該自定義控件庫,在一個頁面中,加入ImageButton控件。選中ImageButton控件,點擊美工板導航欄中的[ImageButton],在彈出的菜單中選擇編輯模板-編輯副本,在彈出的對話框中輸入ImageButtonStyle,選擇該文檔,點擊肯定。blog
6. 在模板編輯狀態下,右鍵點擊文檔大綱面板中的[Border],選擇更改佈局類型-Grid,而後將Grid的背景清空。向Grid中加入三個Image控件,並重置佈局。可從資產面板加入,可在資產面板的搜索欄中輸入Image查找。將三個Image的Width和Height清空,將Stretch屬性改成None。圖片
7. 將三個Image的Source屬性從上到下分別改成模板綁定NormalImage,PressedImage和MouseOverImage,修改方法爲在屬性面板中點擊Source屬性右邊的小方塊,選擇模板綁定-NormalImage。把PressedImage和MouseOverImage的Image的Visibility屬性改成Collapsed。
8. 在狀態面板中,點擊MouseOver,在文檔大綱面板中,選擇第一個Image控件,在屬性面板中,將Visibility屬性改成Collapsed。選擇第三個也就是MouseOverImage的Image控件,在屬性面板中,將Visibility屬性改成Visible。
在狀態面板中,點擊Pressed,在文檔大綱面板中,選擇第一個Image控件,在屬性面板中,將Visibility屬性改成Collapsed。選擇第二個也就是PressedImage的Image控件,在屬性面板中,將Visibility屬性改成Visible。
此時ImageButtonStyle的代碼以下,
<Style TargetType="{x:Type local:ImageButton}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type local:ImageButton}"> <Grid> <VisualStateManager.VisualStateGroups> <VisualStateGroup x:Name="CommonStates"> <VisualState x:Name="Normal"/> <VisualState x:Name="MouseOver"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image"> <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image1"> <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Pressed"> <Storyboard> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image"> <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Collapsed}"/> </ObjectAnimationUsingKeyFrames> <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="image2"> <DiscreteObjectKeyFrame KeyTime="0" Value="{x:Static Visibility.Visible}"/> </ObjectAnimationUsingKeyFrames> </Storyboard> </VisualState> <VisualState x:Name="Disabled"/> </VisualStateGroup> </VisualStateManager.VisualStateGroups> <Image x:Name="image" Source="{TemplateBinding NormalImage}" Stretch="None"/> <Image x:Name="image2" Source="{TemplateBinding PressedImage}" Stretch="None" Visibility="Collapsed"/> <Image x:Name="image1" Source="{TemplateBinding MouseOverImage}" Stretch="None" Visibility="Collapsed"/> </Grid> </ControlTemplate> </Setter.Value> </Setter> </Style>
9. 用這個Style中的ControlTemple部分替換自定義控件庫中的Themes文件夾下的Generic.xaml文件中的ImageButton樣式的ControlTemple部分。注意修改TargetType爲{x:Type local:ImageButton}"。
10. 這時圖片按鈕控件已經完成了,在WPF應用程序項目中的一個頁面上,從資產面板中加入ImageButton控件(選擇項目分類)。選擇ImageButton控件,在屬性面板中能夠看到,在雜項組下,存在NormalImage,MouseOverImage和PressedImage三個屬性,可分別設置圖片。
11. 把這三個屬性設置三張合適的圖片,圖片按鈕便可使用。