在網上找了一下,發現這方面的資料並不多。做傳統桌面的本來就不多了吧,更別說WPF了。我可能也要另尋出路了,不過我還是覺得做桌面挺有意思的。
言歸正傳
首先,新建一個WPF自定義控件庫項目

這里我們封裝一個支持自己繪制形狀的圖片按鈕,且支持圖片和文字。
運行效果如下:(形狀是我隨便繪的)

將默認的CustomControl1.cs改成ImageButton.cs

這個圖片按鈕的實現主要是用WPF的依賴屬性來實現,有疑問的,可以先了解下依賴屬性
https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/advanced/dependency-properties-overview
ImageButton.cs代碼如下:
1 public class ImageButton : System.Windows.Controls.Button 2 { 3 static ImageButton() 4 { 5 DefaultStyleKeyProperty.OverrideMetadata(typeof(ImageButton), new FrameworkPropertyMetadata(typeof(ImageButton))); 6 } 7 8 public static readonly DependencyProperty TextProperty = DependencyProperty.Register("ButtonImage", typeof(string), typeof(FrameworkElement)); 9 10 public string Text 11 { 12 set 13 { 14 SetValue(TextProperty, value); 15 } 16 get 17 { 18 return (string)GetValue(TextProperty); 19 } 20 } 21 }
這里我們只加了一個文字屬性,圖像的顯示我們借助於Button控件本身結構來實現
Button控件的默認控件模版如下
https://docs.microsoft.com/en-us/previous-versions/windows/silverlight/dotnet-windows-silverlight/ms609804%28v%3dvs.95%29(ContentPresenter)
如果要實現圖片+文字,自己加一個Image控件就行了
1 <Border BorderThickness="{TemplateBinding Border.BorderThickness}" BorderBrush="{TemplateBinding Border.BorderBrush}" Background="{TemplateBinding Panel.Background}" Name="border" SnapsToDevicePixels="True"> 2 <ContentPresenter RecognizesAccessKey="True" Content="{TemplateBinding ContentControl.Content}" ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}" ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}" Name="contentPresenter" Margin="{TemplateBinding Control.Padding}" HorizontalAlignment="{TemplateBinding Control.HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding Control.VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding UIElement.SnapsToDevicePixels}" Focusable="False" /> 3 </Border>
然后我們在Themes/Generic.xaml中定義ImageButton的樣式

樣式如下:
1 <Style TargetType="{x:Type local:ImageButton}" BasedOn="{StaticResource {x:Type Button}}"> 2 <Setter Property="Background" Value="Transparent"/> 3 <Setter Property="Template"> 4 <Setter.Value> 5 <ControlTemplate TargetType="{x:Type local:ImageButton}"> 6 <Grid MinHeight="{TemplateBinding MinHeight}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True"> 7 <Grid.RowDefinitions> 8 <RowDefinition Height="Auto"/> 9 <RowDefinition/> 10 </Grid.RowDefinitions> 11 12 <Viewbox x:Name="ViewBoxInternal" Grid.Row="0" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" IsEnabled="{TemplateBinding IsEnabled}" 13 Stretch="Uniform" StretchDirection="Both" Margin="5" Effect="{x:Null}"> 14 <ContentPresenter ContentSource="{TemplateBinding Content}" Width="Auto" Height="Auto" 15 HorizontalAlignment="Center" VerticalAlignment="Center"/> 16 </Viewbox> 17 18 <TextBlock x:Name="TextBlockInternal" Grid.Row="1" Margin="2,0" 19 HorizontalAlignment="Stretch" VerticalAlignment="Center" Text="{Binding Text,RelativeSource={RelativeSource TemplatedParent}}" 20 Effect="{TemplateBinding Effect}" TextAlignment="Center"/> 21 </Grid> 22 </ControlTemplate> 23 </Setter.Value> 24 </Setter> 25 26 <Style.Triggers> 27 <Trigger Property="IsMouseOver" Value="True"> 28 <Setter Property="Background" Value="#FFD5E1F2" /> 29 </Trigger> 30 <Trigger Property="IsPressed" Value="True"> 31 <Setter Property="Background" Value="#FFA3BDE3" /> 32 </Trigger> 33 <Trigger Property="IsEnabled" Value="False"> 34 <Setter Property="Opacity" Value=".6"/> 35 <Setter Property="Effect" Value="{x:Null}"/> 36 </Trigger> 37 </Style.Triggers> 38 </Style>
編譯生成dll
接下來就可以使用了
新建一個WPF工程,先引用 剛才生成的dll,再引入xaml前綴,就可以使用了
xmlns:controls="clr-namespace:ImageButton;assembly=ImageButton"
1 <Window x:Class="ImageButtonDemo.MainWindow" 2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 6 xmlns:local="clr-namespace:ImageButtonDemo" 7 mc:Ignorable="d" 8 xmlns:controls="clr-namespace:ImageButton;assembly=ImageButton" 9 Title="MainWindow" Height="350" Width="525"> 10 <Window.Resources> 11 <Canvas x:Key="Icon.Test" Width="799.758" Height="599.706" Canvas.Left="0" Canvas.Top="0"> 12 <Path x:Name="Path" Width="130.729" Height="144.06" Canvas.Left="348.474" Canvas.Top="149.64" Stretch="Fill" Fill="#FF653B3B" Data="F1 M 370.176,157.7C 363.993,178.312 356.397,198.598 352.176,219.7C 348.227,239.444 344.023,266.44 359.176,279.7C 373.9,292.583 396.612,293.7 416.176,293.7C 432.266,293.7 449.917,291.815 463.176,282.7C 469.226,278.541 474.668,272.599 477.176,265.7C 481.051,255.044 478.176,243.038 478.176,231.7C 478.176,222.95 474.251,214.442 470.176,206.7C 460.316,187.965 452.113,166.402 435.176,153.7C 428.688,148.834 419.287,149.7 411.176,149.7C 399.043,149.7 387.537,155.439 376.176,159.7C 371.568,161.428 367.674,164.701 363.176,166.7C 361.814,167.305 358.122,167.646 359.176,168.7C 360.378,169.902 362.51,168.033 364.176,167.7"/> 13 <Path x:Name="Path_0" Width="65.1971" Height="77.407" Canvas.Left="324.161" Canvas.Top="287.7" Stretch="Fill" Fill="#FF653B3B" Data="F1 M 377.176,296.7C 377.176,294.7 376.364,292.527 377.176,290.7C 377.853,289.177 379.51,287.7 381.176,287.7C 387.139,287.7 390.157,297.818 389.176,303.7C 386.086,322.244 371.611,339.57 355.176,348.7C 349.429,351.893 343.562,354.93 338.176,358.7C 336.344,359.982 334.252,360.869 332.176,361.7C 330.9,362.21 329.463,362.217 328.176,362.7C 326.781,363.223 323.931,366.17 324.176,364.7C 324.693,361.598 327.476,359.345 329.176,356.7C 330.476,354.678 332.101,352.85 333.176,350.7C 339.648,337.755 343.943,322.933 354.176,312.7"/> 14 <Path x:Name="Path_1" Width="45.0698" Height="107.147" Canvas.Left="431.176" Canvas.Top="280.7" Stretch="Fill" Fill="#FF653B3B" Data="F1 M 431.176,292.7C 433.934,306.49 432.661,320.863 435.176,334.7C 437.535,347.674 442.097,360.575 449.176,371.7C 452.848,377.47 457.826,383.16 464.176,385.7C 465.843,386.366 467.526,388.407 469.176,387.7C 470.826,386.993 470.447,384.34 471.176,382.7C 474.337,375.589 475.176,367.481 475.176,359.7C 475.176,349.361 478.153,338.243 474.176,328.7C 473.03,325.948 471.638,323.298 470.176,320.7C 468.635,317.959 467.4,314.923 465.176,312.7C 459.796,307.32 448.266,308.652 445.176,301.7C 442.333,295.303 445.176,287.7 445.176,280.7"/> 15 <Path x:Name="Path_2" Width="43.8764" Height="131.237" Canvas.Left="385.699" Canvas.Top="20.4629" Stretch="Fill" Fill="#FF653B3B" Data="F1 M 395.176,151.7C 395.176,123.031 399.799,93.8116 394.176,65.6997C 391.907,54.3534 382.002,42.0492 387.176,31.6997C 388.341,29.3711 390.143,27.3261 392.176,25.6997C 393.578,24.5784 395.536,24.4288 397.176,23.6997C 398.539,23.0943 399.781,22.2232 401.176,21.6997C 402.463,21.2172 404.033,19.9374 405.176,20.6997C 409.614,23.6581 408.135,32.2621 405.176,36.6997C 404.13,38.2687 400.719,38.8704 401.176,40.6997C 401.581,42.3166 404.998,39.5212 406.176,40.6997C 407.148,41.6716 406.02,43.6149 405.176,44.6997C 403.578,46.7548 400.803,47.6668 399.176,49.6997C 398.055,51.1014 397.176,52.9047 397.176,54.6997C 397.176,57.1265 397.905,59.633 399.176,61.6997C 405.78,72.4312 426.443,72.3991 429.176,84.6997C 431.441,94.8914 423.478,104.795 420.176,114.7C 416.592,125.451 420.176,137.366 420.176,148.7"/> 16 <Path x:Name="Path_3" Width="74.7212" Height="123.254" Canvas.Left="444.122" Canvas.Top="59.4458" Stretch="Fill" Fill="#FF653B3B" Data="F1 M 458.176,178.7C 458.176,169.033 464.643,156.885 458.176,149.7C 453.916,144.966 443.276,143.004 444.176,136.7C 444.387,135.224 446.738,135.092 448.176,134.7C 450.45,134.08 452.924,134.393 455.176,133.7C 460.92,131.932 467.176,131.033 472.176,127.7C 477.625,124.067 469.836,114.684 467.176,108.7C 466.486,107.147 466.676,105.324 466.176,103.7C 465.339,100.978 463.867,98.4627 463.176,95.6997C 461.39,88.556 460.384,79.2906 465.176,73.6997C 471.677,66.1156 483.444,55.8487 492.176,60.6997C 497.916,63.8884 502.063,72.4108 500.176,78.6997C 499.534,80.8415 497.719,82.5304 497.176,84.6997C 496.691,86.64 496.784,88.7385 497.176,90.6997C 499.028,99.9563 513.173,101.695 518.176,109.7C 521.998,115.815 508.248,120.793 506.176,127.7C 503.686,136.001 509.696,145.78 506.176,153.7C 501.21,164.875 482.352,159.733 471.176,164.7C 469.814,165.305 468.51,166.033 467.176,166.7C 465.843,167.366 464.23,167.646 463.176,168.7C 459.586,172.29 461.718,180.429 457.176,182.7"/> 17 <Path x:Name="Path_4" Width="18" Height="13" Canvas.Left="440.176" Canvas.Top="177.7" Stretch="Fill" Fill="#FF653B3B" Data="F1 M 458.176,177.7C 451.305,180.448 445.41,185.466 440.176,190.7"/> 18 </Canvas> 19 </Window.Resources> 20 <Grid> 21 <controls:ImageButton Width="100" Height="100" Content="{StaticResource Icon.Test}" Text="HelloWorld"/> 22 </Grid> 23 </Window>
示例代碼
https://files.cnblogs.com/files/zhaotianff/ImageButtonDemo.zip
2020.07.06新增:
可以通過重寫OnApplyTemplate方法,以便在完整生成模板並將其附加到邏輯樹后執行指定的操作。
如:為控件中的按鈕添加單擊事件。
1 public override void OnApplyTemplate() 2 { 3 base.OnApplyTemplate(); 4 5 close = Template.FindName("PART_Close", this) as System.Windows.Controls.Button; 6 if (close != null) 7 { 8 close.Click += CloseClick; 9 } 10 }
Template(System.Windows.Controls.ControlTemplate)屬性代表當前自定義控件的模板
