在不少的應用程式中,使用者中心的個人頁面經常需要顯示頭像,這個目前主流的做法就是使用者上傳一個圖檔,系統進行截取并顯示為一個圓形的輪廓,即圓形的照片。本文将介紹一下自定義的圖檔控件FlatRoundImage,它是一個UserControl控件,自身攜帶UI樣式和背景邏輯。下面将詳細介紹具體的實作細節。
1 WPF項目結構
基于之前建立的WPF示例項目,在其中建立一個新的關于FlatRoundImage的使用者控件項目檔案。添加過程如下圖所示:

添加成功後,本項目檔案結構,如下圖所示:
與之前的自定義控件不同,使用者控件類型的項目檔案UI和背景邏輯是在一起的,這樣也非常的友善。另外,這種方式建立的自定義控件不需要将其注冊到Generic.xaml檔案中。
2 WPF FlatRoundImage實作
首先,在控件的UI界面上,UserControl類的控件原生帶有UI布局,即像一個視窗一樣,可以通過拖入已有的控件進行UI設計,是以從布局到功能上都更加的友善。FlatRoundImage控件,布局界面如下:
其中的核心代碼如下:
<UserControl x:Class="Yd.WpfControls.FlatRoundImage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Yd.WpfControls"
mc:Ignorable="d"
Width="100"
Height="100"
BorderThickness="0"
RenderOptions.BitmapScalingMode="HighQuality"
UseLayoutRounding="True"
TextOptions.TextFormattingMode="Display"
d:DesignHeight="100" d:DesignWidth="100" x:Name="uc">
<Grid>
<Ellipse Width="{Binding ElementName=uc, Path=Width}"
Height="{Binding ElementName=uc, Path=Width}"
StrokeThickness="1"
SnapsToDevicePixels="True"
Stroke="{Binding ElementName=uc, Path=Stroke}" >
<Ellipse.Fill>
<ImageBrush x:Name="PART_IMG"
ImageSource="{Binding ElementName=uc, Path=ImgSource}" />
<!--<ImageBrush x:Name="PART_IMG" ImageSource="{Binding ImgSource}" /> not work-->
</Ellipse.Fill>
</Ellipse>
</Grid>
</UserControl>
其中的圓形邊框是通過Ellipse實作的,設定長度和寬度一緻,即是圓形。 StrokeThickness="1" 表示邊框寬度為1。圓形中的背景圖是通過Ellipse.Fill屬性的,給出了ImageBrush對象,它具有ImageSource屬性,可綁定具體的圖檔URI。這裡需要注意一下:ImageSource="{Binding ElementName=uc, Path=ImgSource}"這種綁定是成功的,而ImageSource="{Binding ImgSource}"是無法正确綁定屬性的。
下面再給出FlatRoundImage自定義控件的背景代碼,具體如下所示:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
namespace Yd.WpfControls
{
/// <summary>
/// FlatRoundImage.xaml 的互動邏輯
/// </summary>
public partial class FlatRoundImage : UserControl
{
public FlatRoundImage()
{
InitializeComponent();
}
public static readonly DependencyProperty ImgSourceProperty =
DependencyProperty.Register("ImgSource", typeof(string), typeof(FlatRoundImage)
,new PropertyMetadata("/Image/avatar.png"));
public string ImgSource
{
get { return (string)GetValue(ImgSourceProperty); }
set
{
SetValue(ImgSourceProperty, value);
}
}
public static readonly DependencyProperty StrokeProperty =
DependencyProperty.Register("Stroke", typeof(Brush), typeof(FlatRoundImage)
, new PropertyMetadata(Brushes.Silver));
public Brush Stroke
{
get { return (Brush)GetValue(StrokeProperty); }
set
{
SetValue(StrokeProperty, value);
}
}
}
}
其中定義了兩個控件的依賴屬性,即ImgSource和Stroke,一個代表背景圖檔的位址,一個代表邊框的顔色。
3 WPF FlatRoundImage測試
首先,需要重新生成一下項目檔案,然後在WpfControls項目中添加一個視窗Window6,并在此視窗中添加自定義控件FlatRoundImage,Window6.xaml部分示例代碼如下:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfControls"
xmlns:WpfControls="clr-namespace:Yd.WpfControls;assembly=Yd.WpfControls" x:Class="WpfControls.Window6"
mc:Ignorable="d"
Title="Window6" Height="350" Width="400">
<Grid Background="Green">
<WpfControls:FlatRoundImage HorizontalAlignment="Center" Margin="0,93,0,0"
VerticalAlignment="Top" ImgSource="/Image/avatar.png"/>
<WpfControls:FlatRoundImage HorizontalAlignment="Center" Margin="0,222,0,0"
Height="60" Width="60"
VerticalAlignment="Top" ImgSource="/Image/avatar.png"/>
</Grid>
</Window>
另外需要注意的就是,圖檔路徑如果無法找到,則可能需要進行圖檔素材的輸出資源配置,将其作為資源輸出到目錄中,示意圖如下所示:
運作界面如下: