WPF 實現 Gitee 氣泡菜單(一)

?WPF 實現 Gitee 氣泡菜單(一)

氣泡菜單(一)

作者:WPFDevelopersOrg

原文鏈接: ? ?https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用大于等于.NET40

  • Visual Studio 2022;

  • 項目使用 MIT 開源許可協議;

a130051d15e5b9c44bc84c4bbb06b36f.png
  • 需要實現氣泡菜單需要使用Canvas畫布進行添加內容;

  • 但是為了使用方便需要在ListBox中使用Canvas做為ItemsPanelTemplate

  • 使用時只需要在ListBox中添加ListBoxItem就行;

1) BubbleControl.cs 代碼如下;

  • BubbleControl.cs 繼承 Control創建依賴屬性Content

  • 根據Content集合循環隨機生成WidthHeight在生成SetLeftSetTop 需要判斷重疊面積不能超過當前面積的百分之六十~九十;

using?System;
using?System.Collections.Generic;
using?System.Collections.ObjectModel;
using?System.Diagnostics;
using?System.Linq;
using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Media;
using?System.Windows.Shapes;
using?WPFDevelopers.Helpers;namespace?WPFDevelopers.Controls
{[TemplatePart(Name?=?BorderTemplateName,?Type?=?typeof(Border))]public?class?BubbleControl?:?ContentControl{private?const?string?BorderTemplateName?=?"PART_Border";public?new?static?readonly?DependencyProperty?ContentProperty?=DependencyProperty.Register("Content",?typeof(ObservableCollection<BubbleItem>),?typeof(BubbleControl),new?PropertyMetadata(null));public?new?static?readonly?DependencyProperty?BorderBackgroundProperty?=DependencyProperty.Register("BorderBackground",?typeof(Brush),?typeof(BubbleControl),new?PropertyMetadata(null));private?Border?_border;private?double?_bubbleItemX,?_bubbleItemY;private?Ellipse?_ellipse;private?int?_number;private?readonly?List<Rect>?_rects?=?new?List<Rect>();private?RotateTransform?_rotateTransform;private?double?_size;private?const?int?_maxSize?=?120;static?BubbleControl(){DefaultStyleKeyProperty.OverrideMetadata(typeof(BubbleControl),new?FrameworkPropertyMetadata(typeof(BubbleControl)));}public?BubbleControl(){Loaded?+=?delegate{double?left?=?0d,?top?=?0d;for?(var?y?=?0;?y?<?(int)Height?/?_maxSize;?y++){double?yNum?=?y?+?1;yNum?=?_maxSize?*?yNum;for?(var?x?=?0;?x?<?(int)Width?/?_maxSize;?x++){if?(_number?>?Content.Count?-?1)return;var?item?=?Content[_number];if?(double.IsNaN(item.Width)?||?double.IsNaN(item.Height))SetBubbleItem(item);_bubbleItemX?=?Canvas.GetLeft(item);_bubbleItemY?=?Canvas.GetTop(item);if?(double.IsNaN(_bubbleItemX)?||?double.IsNaN(_bubbleItemY)){double?xNum?=?x?+?1;xNum?=?_maxSize?*?xNum;_bubbleItemX?=?ControlsHelper.NextDouble(left,xNum?-?_size??*?ControlsHelper.NextDouble(0.6,0.9));var?_width?=?_bubbleItemX?+?_size;_width?=?_width?>?Width???Width?-?(Width?-?_bubbleItemX)?-?_size?:?_bubbleItemX;_bubbleItemX?=?_width;_bubbleItemY?=?ControlsHelper.NextDouble(top,yNum?-?_size?*?ControlsHelper.NextDouble(0.6,?0.9));var?_height?=?_bubbleItemY?+?_size;_height?=?_height?>?Height???Height?-?(Height?-?_bubbleItemY)?-?_size?:?_bubbleItemY;_bubbleItemY?=?_height;}Canvas.SetLeft(item,?_bubbleItemX);Canvas.SetTop(item,?_bubbleItemY);left?=?left?+?_size;if?(item.Background?is?null)item.Background?=?ControlsHelper.RandomBrush();_rects.Add(new?Rect(_bubbleItemX,?_bubbleItemY,?_size,?_size));_number++;}left?=?0d;top?=?top?+?_maxSize;}};}public?new?ObservableCollection<BubbleItem>?Content{get?=>?(ObservableCollection<BubbleItem>)GetValue(ContentProperty);set?=>?SetValue(ContentProperty,?value);}public?Brush?BorderBackground{get?=>?(Brush)this.GetValue(BorderBackgroundProperty);set?=>?this.SetValue(BorderBackgroundProperty,?(object)value);}private?void?SetBubbleItem(BubbleItem?item){if?(item.Text.Length?>=?4)_size?=?ControlsHelper.GetRandom.Next(80,?_maxSize);else_size?=?ControlsHelper.GetRandom.Next(50,?_maxSize);item.Width?=?_size;item.Height?=?_size;}public?override?void?OnApplyTemplate(){base.OnApplyTemplate();_border?=?GetTemplateChild(BorderTemplateName)?as?Border;}public?override?void?BeginInit(){Content?=?new?ObservableCollection<BubbleItem>();base.BeginInit();}}
}

2) ControlsHelper.cs 代碼如下;

  • 隨機Double值;

  • 隨機顏色;

private?static?long?_tick?=?DateTime.Now.Ticks;public?static?Random?GetRandom?=?new?Random((int)(_tick?&?0xffffffffL)?|?(int)(_tick?>>?32));public?static?double?NextDouble(double?miniDouble,?double?maxiDouble){if?(GetRandom?!=?null){return?GetRandom.NextDouble()?*?(maxiDouble?-?miniDouble)?+?miniDouble;}else{return?0.0d;}}public?static?Brush?RandomBrush(){var?R?=?GetRandom.Next(255);var?G?=?GetRandom.Next(255);var?B?=?GetRandom.Next(255);var?color?=?Color.FromRgb((byte)R,?(byte)G,?(byte)B);var?solidColorBrush?=?new?SolidColorBrush(color);return?solidColorBrush;}

3) BubbleItem.cs 代碼如下;

using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Input;namespace?WPFDevelopers
{public?class?BubbleItem?:?ListBoxItem{public?static?readonly?DependencyProperty?TextProperty?=DependencyProperty.Register("Text",?typeof(string),?typeof(BubbleItem),new?PropertyMetadata(string.Empty));public?static?readonly?DependencyProperty?SelectionCommandProperty?=DependencyProperty.Register("SelectionCommand",?typeof(ICommand),?typeof(BubbleItem),new?PropertyMetadata(null));static?BubbleItem(){DefaultStyleKeyProperty.OverrideMetadata(typeof(BubbleItem),new?FrameworkPropertyMetadata(typeof(BubbleItem)));}public?string?Text{get?=>?(string)GetValue(TextProperty);set?=>?SetValue(TextProperty,?value);}public?ICommand?SelectionCommand{get?=>?(ICommand)GetValue(SelectionCommandProperty);set?=>?SetValue(SelectionCommandProperty,?value);}}
}

4) BubbleControl.xaml 代碼如下;

<ResourceDictionary?xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="clr-namespace:WPFDevelopers.Controls"><Style?TargetType="{x:Type?controls:BubbleControl}"><Setter?Property="Width"?Value="400"/><Setter?Property="Height"?Value="400"/><Setter?Property="Template"><Setter.Value><ControlTemplate?TargetType="local:BubbleControl"><Grid?Width="{TemplateBinding?Width}"?Height="{TemplateBinding?Height}"><Border?BorderBrush="#E9E9E9"?BorderThickness="1"?Background="#FAFAFA"?Margin="45"CornerRadius="400"x:Name="PART_Border"><Ellipse?Fill="#FFFFFF"?Margin="20"/></Border><ListBox?ItemsSource="{TemplateBinding?Content}"Background="Transparent"?BorderBrush="Transparent"ScrollViewer.HorizontalScrollBarVisibility="Disabled"ScrollViewer.VerticalScrollBarVisibility="Disabled"><ListBox.ItemContainerStyle><Style?TargetType="{x:Type?local:BubbleItem}"><Setter?Property="Canvas.Left"?Value="{Binding?(Canvas.Left)}"/><Setter?Property="Canvas.Top"?Value="{Binding?(Canvas.Top)}"/><ResourceDictionary?xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:controls="clr-namespace:WPFDevelopers.Controls"><ResourceDictionary.MergedDictionaries><ResourceDictionary?Source="Basic/ControlBasic.xaml"/><ResourceDictionary?Source="Basic/Animations.xaml"/></ResourceDictionary.MergedDictionaries><Style?TargetType="{x:Type?controls:BubbleControl}"?BasedOn="{StaticResource?ControlBasicStyle}"><Setter?Property="Width"?Value="400"/><Setter?Property="Height"?Value="400"/><Setter?Property="Background"?Value="{StaticResource?WhiteSolidColorBrush}"/><Setter?Property="BorderThickness"?Value="1"/><Setter?Property="BorderBrush"?Value="{StaticResource?SecondaryTextSolidColorBrush}"/><Setter?Property="BorderBackground"?Value="{StaticResource?BaseSolidColorBrush}"/><Setter?Property="Template"><Setter.Value><ControlTemplate?TargetType="controls:BubbleControl"><Grid?Width="{TemplateBinding?Width}"?Height="{TemplateBinding?Height}"><Border?BorderBrush="{TemplateBinding?BorderBrush}"BorderThickness="{TemplateBinding?BorderThickness}"?Background="{TemplateBinding?BorderBackground}"?Margin="45"CornerRadius="400"x:Name="PART_Border"><Ellipse?Fill="{TemplateBinding?Background}"?Margin="20"/></Border><ListBox?ItemsSource="{TemplateBinding?Content}"Background="Transparent"?BorderBrush="Transparent"ScrollViewer.HorizontalScrollBarVisibility="Disabled"ScrollViewer.VerticalScrollBarVisibility="Disabled"Style="{x:Null}"><ListBox.ItemContainerStyle><Style?TargetType="{x:Type?controls:BubbleItem}"><Setter?Property="Canvas.Left"?Value="{Binding?(Canvas.Left)}"/><Setter?Property="Canvas.Top"?Value="{Binding?(Canvas.Top)}"/><Setter?Property="Template"><Setter.Value><ControlTemplate?TargetType="controls:BubbleItem"><Grid?Width="{TemplateBinding?Width}"?Height="{TemplateBinding?Height}"><Ellipse?Fill="{TemplateBinding?Background}"?Opacity=".6"/><TextBlock?VerticalAlignment="Center"?HorizontalAlignment="Center"Padding="10,0"><Hyperlink?Foreground="{StaticResource?BlackSolidColorBrush}"Command="{TemplateBinding?SelectionCommand}"><TextBlock?Text="{TemplateBinding?Text}"TextAlignment="Center"TextTrimming="CharacterEllipsis"ToolTip="{TemplateBinding?Text}"/></Hyperlink></TextBlock></Grid><ControlTemplate.Triggers></ControlTemplate.Triggers></ControlTemplate></Setter.Value></Setter></Style></ListBox.ItemContainerStyle><ListBox.ItemsPanel><ItemsPanelTemplate><Canvas?IsItemsHost="True"?Width="{TemplateBinding?Width}"?Height="{TemplateBinding?Height}"/></ItemsPanelTemplate></ListBox.ItemsPanel></ListBox></Grid></ControlTemplate></Setter.Value></Setter></Style></ResourceDictionary>

5) BubbleControlExample.xaml 代碼如下;

<local:BubbleControl?x:Name="MyBubbleControl"><wpfdev:BubbleControl.Content><wpfdev:BubbleItem??Text="WPF"?SelectionCommand="{Binding?WPFCommand,RelativeSource={RelativeSource?AncestorType=local:BubbleControlExample}}"/><wpfdev:BubbleItem??Text="ASP.NET"/><wpfdev:BubbleItem??Text="WinUI"/><wpfdev:BubbleItem??Text="WebAPI"/><wpfdev:BubbleItem??Text="Blazor"/><wpfdev:BubbleItem??Text="MAUI"SelectionCommand="{Binding?MAUICommand,RelativeSource={RelativeSource?AncestorType=local:BubbleControlExample}}"/><wpfdev:BubbleItem??Text="Xamarin"/><wpfdev:BubbleItem??Text="WinForm"/><wpfdev:BubbleItem??Text="UWP"/></wpfdev:BubbleControl.Content></local:BubbleControl>

6) BubbleControlExample.xaml.cs 代碼如下;

using?System.Windows.Controls;
using?System.Windows.Input;
using?WPFDevelopers.Samples.Helpers;namespace?WPFDevelopers.Samples.ExampleViews
{///?<summary>///?BubbleControlExample.xaml?的交互邏輯///?</summary>public?partial?class?BubbleControlExample?:?UserControl{public?BubbleControlExample(){InitializeComponent();}public?ICommand?WPFCommand?=>?new?RelayCommand(delegate{WPFDevelopers.Minimal.Controls.MessageBox.Show("點擊了“WPF開發者”.",?"提示");});public?ICommand?MAUICommand?=>?new?RelayCommand(delegate{WPFDevelopers.Minimal.Controls.MessageBox.Show("點擊了“MAUI開發者”.",?"提示");});}
}
3fe55e1fbeae60d59bc62eea496330b7.png

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/284391.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/284391.shtml
英文地址,請注明出處:http://en.pswp.cn/news/284391.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

[轉]LVS負載均衡(LVS簡介、三種工作模式、十種調度算法)

一、LVS簡介 LVS&#xff08;Linux Virtual Server&#xff09;即Linux虛擬服務器&#xff0c;是由章文嵩博士主導的開源負載均衡項目&#xff0c;目前LVS已經被集成到Linux內核模塊中。該項目在Linux內核中實現了基于IP的數據請求負載均衡調度方案&#xff0c;其體系結構如圖1…

一張圖看懂微軟Power BI系列組件

一、Power BI簡介 Power BI是微軟最新的商業智能&#xff08;BI&#xff09;概念&#xff0c;它包含了一系列的組件和工具。話不多說&#xff0c;直接上圖吧&#xff1a; Power BI的核心理念就是讓我們用戶不需要強大的技術背景&#xff0c;只需要掌握Excel這樣簡單的工具就能快…

互聯網項目總結

2019獨角獸企業重金招聘Python工程師標準>>> 從去年年底開始專門被分配到互聯網小組做項目&#xff0c;一直想做個總結&#xff0c;但是苦于太貪玩。好吧&#xff0c;借著小組技術交流來一發。這里只對自己新學習的技術或者一些小技巧做簡要概述&#xff0c;不做深究…

【ArcGIS微課1000例】0036:分式標注案例教程

【拓展閱讀】:【ArcGIS Pro微課1000例】0015:ArcGIS Pro中屬性字段分式標注案例教程 文章目錄 1. 符號化2. 分式標注1. 符號化 右鍵數據圖層→符號系統,打開符號系統對話框,住符號系統選擇【唯一值】,字段1選擇NAME。 唯一值標注效果: 2. 分式標注 雙擊打開圖層屬性,切…

【轉】 ConstraintLayout 完全解析 快來優化你的布局吧

轉自&#xff1a; http://blog.csdn.net/lmj623565791/article/details/78011599 本文出自張鴻洋的博客 一、概述 ConstraintLayout出現有一段時間了&#xff0c;不過一直沒有特別去關注&#xff0c;也多多少少看了一些文字介紹&#xff0c;多數都是對使用可視化布局拖拽&#…

IoTDB 的C# 客戶端發布 0.13.0.7

IoTDB C# Client 0.13.0.7 已經發布&#xff0c; 此版本更新的內容為筆者為Apache-IoTDB-Client-CSharp實現了Ado.Net的兼容層&#xff0c;降低了對IoTDB的使用門檻。于此同時&#xff0c; IoTSharp也開始支持了IoTDB的數據入庫&#xff0c;隨著晚些時候IoTSharp 2.7 版本的發布…

[轉]Docker超詳細基礎教程,快速入門docker

一、docker概述 1.什么是docker Docker 是一個開源的應用容器引擎&#xff0c;基于 Go 語言 并遵從 Apache2.0 協議開源。 Docker 可以讓開發者打包他們的應用以及依賴包到一個輕量級、可移植的容器中&#xff0c;然后發布到任何流行的 Linux 機器上&#xff0c;也可以實現虛擬…

【Zookeeper】源碼分析之服務器(一)

一、前言 前面已經介紹了Zookeeper中Leader選舉的具體流程&#xff0c;接著來學習Zookeeper中的各種服務器。 二、總體框架圖 對于服務器&#xff0c;其框架圖如下圖所示 說明&#xff1a; ZooKeeperServer&#xff0c;為所有服務器的父類&#xff0c;其請求處理鏈為PrepReques…

linux下配置samba服務器(以CentOS6.7為例)

一、簡介&#xff08;百度百科&#xff09;Samba是在Linux和UNIX系統上實現SMB協議的一個免費軟件&#xff0c;由服務器及客戶端程序構成。SMB&#xff08;Server Messages Block&#xff0c;信息服務塊&#xff09;是一種在局域網上共享文件和打印機的一種通信協議&#xff0c…

【ArcGIS微課1000例】0037:上下標標注記案例教程

在利用ArcGIS進行制圖時&#xff0c;進行標注(Label) 或注記(Annolation) 是必不可少的。但是除了常規的標注和注記以外&#xff0c;還時常需要一些特殊的標注或注記&#xff0c;比如上標、下標等。 文章目錄一、上標標注方法二、下標標注方法一、上標標注方法 上下標代碼模板…

Redis——緩存擊穿、穿透、雪崩

1、緩存穿透&#xff1a; &#xff08;1&#xff09;問題描述&#xff1a;key對應的數據并不存在&#xff0c;每次請求訪問key時&#xff0c;緩存中查找不到&#xff0c;請求都會直接訪問到數據庫中去&#xff0c;請求量超出數據庫時&#xff0c;便會導致數據庫崩潰。如一個用…

數據庫性能系列之子查詢

前言說起數據庫&#xff0c;想必一些朋友會認為&#xff0c;數據庫不就是天天CRUD嗎&#xff1f;只要我掌握了這幾招&#xff0c;根本不在話下。是的&#xff0c;其實我也很贊同這個觀點&#xff0c;對于大多數應用程序來說&#xff0c;只掌握這些內容&#xff0c;是可以勝任日…

shell printf命令:格式化輸出語句

shell printf命令&#xff1a;格式化輸出語句注意&#xff1a;使用printf的腳本比使用echo移植性好。如同echo命令&#xff0c;printf命令可以輸出簡單的字符串&#xff1a;[rootmaster ~]#printf "Hello, Shell\n"Hello, Shellprintf不像echo那樣會自動提供一個換行…

UVa 10905 孩子們的游戲

https://vjudge.net/problem/UVA-10905 題意&#xff1a; 給定n個正整數&#xff0c;把它們連接成一個最大的整數。 思路&#xff1a; 實在是沒想到直接用string來排序了。 1 #include<iostream> 2 #include<algorithm>3 #include<string>4 using namespace …

laravel 內部驗證碼

為什么80%的碼農都做不了架構師&#xff1f;>>> 1.找到此文件composer.json 如下圖添加 "gregwar/captcha": "1.*" 行代碼 2.在命令行中執行 composer update 安裝完成后 3.找到控制器添加如下代碼 public function captcha($tmp) {//生成驗證…

k8s docker集群搭建

一、Kubernetes系列之介紹篇 1.背景介紹 云計算飛速發展 - IaaS - PaaS - SaaS Docker技術突飛猛進 - 一次構建&#xff0c;到處運行 - 容器的快速輕量 - 完整的生態環境 2.什么是kubernetes 首先&#xff0c;他是一個全新的基于容器技術的分布式架構領先方案。Kubernetes(k8…

leetcode 66 Plus One

給定一個數組&#xff0c;表示整數的各個位數&#xff0c;現要將其加上1&#xff0c;考慮進位。 vector<int> plusOne(vector<int>& digits) {int size digits.size();bool carry true;for (int i size - 1; i > 0; --i) {if (digits[i] 9 && c…

如何讓最小 API 綁定查詢字符串中的數組

前言在上次的文章中&#xff0c;我們實現了《讓 ASP.NET Core 支持綁定查詢字符串中的數組》&#xff1a;[HttpGet] public string Get([FromQuery][ModelBinder(BinderType typeof(IntArrayModelBinder))] int[] values) {return string.Join(" ", values.Select(p…

Kubernetes api-server源碼閱讀2(Debug Kubernetes篇)

云原生學習路線導航頁&#xff08;持續更新中&#xff09; 本文是 Kubernetes api-server源碼閱讀 系列第二篇&#xff0c;主要講述如何實現 kubernetes api-server 的 debug 參考b站視頻地址&#xff1a;Kubernetes源碼開發之旅二 1.本篇章任務 Go-Delve&#xff1a;go語言的…

webrtc 視頻 demo

webrtc 視頻 demo webrtc網上封裝的很多&#xff0c;demo很多都是一個頁面里實現的&#xff0c;今天實現了個完整的 &#xff0c; A 發視頻給 BA webrtc.html作為offer <!DOCTYPE html> <html id"home" lang"en"><head><meta http-e…