日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > asp.net >内容正文

asp.net

WPF 中使用附加属性,将任意 UI 元素或控件裁剪成圆形(椭圆)

發(fā)布時(shí)間:2025/3/20 asp.net 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WPF 中使用附加属性,将任意 UI 元素或控件裁剪成圆形(椭圆) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
原文:WPF 中使用附加屬性,將任意 UI 元素或控件裁剪成圓形(橢圓)

版權(quán)聲明:本作品采用知識(shí)共享署名-非商業(yè)性使用-相同方式共享 4.0 國(guó)際許可協(xié)議進(jìn)行許可。歡迎轉(zhuǎn)載、使用、重新發(fā)布,但務(wù)必保留文章署名呂毅(包含鏈接:http://blog.csdn.net/wpwalter/),不得用于商業(yè)目的,基于本文修改后的作品務(wù)必以相同的許可發(fā)布。如有任何疑問(wèn),請(qǐng)與我聯(lián)系(walter.lv@qq.com)。 https://blog.csdn.net/WPwalter/article/details/80820818

不知從什么時(shí)候開(kāi)始,頭像流行使用圓形了,于是各個(gè)平臺(tái)開(kāi)始追逐顯示圓形裁剪圖像的技術(shù)。WPF 作為一個(gè)優(yōu)秀的 UI 框架,當(dāng)然有其內(nèi)建的機(jī)制支持這種圓形裁剪。

不過(guò),內(nèi)建的機(jī)制僅支持畫(huà)刷,而如果被裁剪的元素支持交互,或者擁有普通畫(huà)刷無(wú)法達(dá)到的顯示效果,那么就需要本文介紹的更加通用的解決方法了。


UWP 的圓形裁剪請(qǐng)左轉(zhuǎn)參考:UWP 將圖片裁剪成圓形(橢圓)。

WPF 的 UIElement 提供了 Clip 依賴項(xiàng)屬性,可以使用一個(gè) Geometry 來(lái)裁剪任意的 UIElement。由于 Geometry 幾乎可以表示任意形狀,這意味著我們可以才建成任意想要的樣子。

于是,我們可以利用這一點(diǎn),使用 EllipseGeometry 將任意 UIElement 裁剪成圓形或者橢圓形。比如,寫(xiě)成下面這樣:

<Grid><Grid.Clip><EllipseGeometry Center="120 180" RadiusX="120" RadiusY="180" /></Grid.Clip><Image Source="demo.jpg" Stretch="Fill" /><TextBlock Text="https://walterlv.github.io" Foreground="White" Margin="171,172,51,21"/> </Grid>

最終可以出現(xiàn)如下的效果。

不過(guò),稍微改變下窗口的大小,就會(huì)發(fā)現(xiàn)裁剪的范圍不對(duì)了。因?yàn)槲覀儗?xiě)死了圓形裁剪的中心點(diǎn)和兩個(gè)不同方向的半徑(這里可不好說(shuō)是長(zhǎng)半軸還是短半軸啊)。

我們需要一個(gè)可以自動(dòng)修改裁剪圓形的一種機(jī)制,于是,我們想到了 Binding。為了使 XAML 的代碼好看一點(diǎn),我將 Binding 封裝到了一個(gè)單獨(dú)的類中處理,使用附加屬性提供 API。

我封裝好的類如下:

/// <summary> /// 提供將任意控件裁剪為圓形或橢圓的附加屬性。 /// </summary> public static class EllipseClipper {/// <summary>/// 標(biāo)識(shí) IsClipping 的附加屬性。/// </summary>public static readonly DependencyProperty IsClippingProperty = DependencyProperty.RegisterAttached("IsClipping", typeof(bool), typeof(EllipseClipper), new PropertyMetadata(false, OnIsClippingChanged));public static void SetIsClipping(DependencyObject element, bool value)=> element.SetValue(IsClippingProperty, value);public static bool GetIsClipping(DependencyObject element)=> (bool) element.GetValue(IsClippingProperty);private static void OnIsClippingChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){var source = (UIElement) d;if (e.NewValue is false){// 如果 IsClipping 附加屬性被設(shè)置為 false,則清除 UIElement.Clip 屬性。source.ClearValue(UIElement.ClipProperty);return;}// 如果 UIElement.Clip 屬性被用作其他用途,則拋出異常說(shuō)明問(wèn)題所在。var ellipse = source.Clip as EllipseGeometry;if (source.Clip != null && ellipse == null){throw new InvalidOperationException($"{typeof(EllipseClipper).FullName}.{IsClippingProperty.Name} " +$"is using {source.GetType().FullName}.{UIElement.ClipProperty.Name} " +"for clipping, dont use this property manually.");}// 使用 UIElement.Clip 屬性。ellipse = ellipse ?? new EllipseGeometry();source.Clip = ellipse;// 使用綁定來(lái)根據(jù)控件的寬高更新橢圓裁剪范圍。var xBinding = new Binding(FrameworkElement.ActualWidthProperty.Name){Source = source,Mode = BindingMode.OneWay,Converter = new HalfConverter(),};var yBinding = new Binding(FrameworkElement.ActualHeightProperty.Name){Source = source,Mode = BindingMode.OneWay,Converter = new HalfConverter(),};var xyBinding = new MultiBinding{Converter = new SizeToClipCenterConverter(),};xyBinding.Bindings.Add(xBinding);xyBinding.Bindings.Add(yBinding);BindingOperations.SetBinding(ellipse, EllipseGeometry.RadiusXProperty, xBinding);BindingOperations.SetBinding(ellipse, EllipseGeometry.RadiusYProperty, yBinding);BindingOperations.SetBinding(ellipse, EllipseGeometry.CenterProperty, xyBinding);}private sealed class SizeToClipCenterConverter : IMultiValueConverter{public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)=> new Point((double) values[0], (double) values[1]);public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)=> throw new NotSupportedException();}private sealed class HalfConverter : IValueConverter{public object Convert(object value, Type targetType, object parameter, CultureInfo culture)=> (double) value / 2;public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)=> throw new NotSupportedException();} }

在 XAML 中只需要很簡(jiǎn)單的一個(gè)屬性賦值即可達(dá)到圓形或橢圓形裁剪。

<Grid local:EllipseClipper.IsClipping="True"><Image Source="fluentdesign-app-header.jpg" Stretch="Fill" /><TextBlock Text="https://walterlv.github.io" Foreground="White" Margin="171,172,51,21"/> </Grid>

而且才控件的大小改變的時(shí)候也能夠正常更新裁剪范圍。

這篇博客的核心代碼我也貼在了 StackOverflow 上:c# - WPF displaying a gif in an ellipse - Stack Overflow

總結(jié)

以上是生活随笔為你收集整理的WPF 中使用附加属性,将任意 UI 元素或控件裁剪成圆形(椭圆)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。