WPF 實現視頻會議與會人員動態布局

?WPF 實現視頻會議與會人員動態布局

控件名:SixGridView

作 ? 者:WPFDevelopersOrg - 驚鏵

原文鏈接[1]:https://github.com/WPFDevelopersOrg/WPFDevelopers

  • 框架使用.NET40

  • Visual Studio 2019;

  • 接著上一篇是基于Grid實現的視頻查看感覺有點浪費,所以修改為基于Panel又重新實現了。

  • Panel EndInit()后繪制鼠標經過的選中效果。

  • 當鼠標移動到候選封面區時,動畫從上一次鼠標的位置到當前鼠標位置做移動動畫。

39a328dee1f0442edc8c08c1c1a84bdf.png

1)新建 SixGirdView.cs 代碼如下:

using?System;
using?System.Collections.Generic;
using?System.Linq;
using?System.Windows;
using?System.Windows.Controls;
using?System.Windows.Input;
using?System.Windows.Media;
using?System.Windows.Media.Animation;namespace?WPFDevelopers.Controls
{public?class?SixGirdView?:?Panel{public?static?readonly?DependencyProperty?SelectBrushProperty?=DependencyProperty.Register("SelectBrush",?typeof(Brush),?typeof(SixGirdView),new?PropertyMetadata(Brushes.Red));public?static?readonly?DependencyProperty?BorderThicknessProperty?=DependencyProperty.Register("BorderThickness",?typeof(Thickness),?typeof(SixGirdView),new?PropertyMetadata(new?Thickness(1)));private?readonly?Dictionary<Rect,?int>?_dicRect?=?new?Dictionary<Rect,?int>();private?readonly?int?_columns?=?3;private?readonly?int?_rows?=?3;private?Border?_border;private?int?_last;private?Rect?_lastRect;private?Storyboard?_storyboard;public?Brush?SelectBrush{get?=>?(Brush)?GetValue(SelectBrushProperty);set?=>?SetValue(SelectBrushProperty,?value);}public?Thickness?BorderThickness{get?=>?(Thickness)?GetValue(BorderThicknessProperty);set?=>?SetValue(BorderThicknessProperty,?value);}public?override?void?EndInit(){base.EndInit();var?children?=?InternalChildren;if?(_border?==?null?&&?children.Count?>=?1){_border?=?new?Border{BorderThickness?=?BorderThickness,BorderBrush?=?SelectBrush};_border.RenderTransform?=?new?TranslateTransform();children.Add(_border);}}protected?override?Size?MeasureOverride(Size?availableSize){var?children?=?InternalChildren;int?numCol?=?0,?numRow?=?0;var?isRow?=?false;Point?point?=?default;Size?size?=?default;_dicRect.Clear();double?_width?=?availableSize.Width?/?_columns,?_height?=?availableSize.Height?/?_rows;for?(int?i?=?0,?count?=?children.Count;?i?<?count;?++i){if?(i?>=?6)?continue;var?uIElement?=?children[i];if?(uIElement?!=?null){uIElement.Measure(availableSize);if?(i?==?0){point?=?new?Point(0,?0);size?=?new?Size(availableSize.Width?/?_columns?*?2,?availableSize.Height?/?_rows?*?2);numRow++;}else{var?num?=?i?-?1;var?x?=?0d;if?(!isRow){x?=?_width?*?2;numCol?=?numRow?+?1;if?(numCol?<?_columns){point?=?new?Point(x,?0);}else{point?=?new?Point(x,?_height);isRow?=?true;numCol?=?0;}numRow++;}else{x?=?_width?*?numCol;numCol++;x?=?x?>=?availableSize.Width???0?:?x;point?=?new?Point(x,?_height?*?2);}size?=?new?Size(_width,?_height);}uIElement.Arrange(new?Rect(point,?size));if?(i?>=?6?||?i?==?0)?continue;var?rect?=?new?Rect(point.X,?point.Y,?size.Width,?size.Height);_dicRect.Add(rect,?i);}}_last?=?_last?==?0???1?:?_last;if?(_border?!=?null){_border.Measure(availableSize);point?=?new?Point(0,?0);size?=?new?Size(availableSize.Width?/?_columns,?availableSize.Height?/?_columns);_border.Arrange(new?Rect(point,?size));var?_translateTransform?=?(TranslateTransform)?_border.RenderTransform;if?(_last?==?1){_translateTransform.X?=?availableSize.Width?/?_columns?*?2;}else{var?uIElement?=?InternalChildren[_last];if?(uIElement?!=?null){var?rect?=?_dicRect.FirstOrDefault(x?=>?x.Value?==?_last).Key;if?(rect?!=?null){point?=?new?Point(rect.X,?rect.Y);CreateStoryboard(point);}}}}return?availableSize;}protected?override?void?OnPreviewMouseMove(MouseEventArgs?e){base.OnPreviewMouseMove(e);var?currentPoint?=?e.GetPosition(this);if?(_lastRect.Contains(currentPoint))return;var?model?=?_dicRect.Keys.FirstOrDefault(x?=>?x.Contains(currentPoint));if?(model?==?default)?return;_dicRect.TryGetValue(model,?out?_last);if?(_border?==?null)?return;CreateStoryboard(new?Point(model.X,?model.Y));_lastRect?=?model;}private?void?CreateStoryboard(Point?point){var?sineEase?=?new?SineEase?{EasingMode?=?EasingMode.EaseOut};if?(_storyboard?==?null){_storyboard?=?new?Storyboard();}else{_storyboard.Stop();_storyboard.Children.Clear();}var?animationX?=?new?DoubleAnimation{Duration?=?TimeSpan.FromMilliseconds(500),To?=?point.X,EasingFunction?=?sineEase};Storyboard.SetTargetProperty(animationX,new?PropertyPath("(Border.RenderTransform).(TranslateTransform.X)"));_storyboard.Children.Add(animationX);var?animationY?=?new?DoubleAnimation{Duration?=?TimeSpan.FromMilliseconds(500),To?=?point.Y,EasingFunction?=?sineEase};Storyboard.SetTargetProperty(animationY,new?PropertyPath("(Border.RenderTransform).(TranslateTransform.Y)"));_storyboard.Children.Add(animationY);_storyboard.Begin(_border);}}
}

2)新建 SixGirdViewExample.xaml 代碼如下:

<UserControl?x:Class="WPFDevelopers.Samples.ExampleViews.SixGirdViewExample"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:wpfdev="https://github.com/WPFDevelopersOrg/WPFDevelopers"xmlns:controls="clr-namespace:WPFDevelopers.Samples.Controls"xmlns:local="clr-namespace:WPFDevelopers.Samples.ExampleViews"mc:Ignorable="d"?d:DesignHeight="450"?d:DesignWidth="800"><controls:CodeViewer><wpfdev:SixGirdView?BorderThickness="1"?SelectBrush="Red"><wpfdev:SixGirdView.Resources><Style?TargetType="TextBlock"><Setter?Property="Foreground"?Value="White"/><Setter?Property="VerticalAlignment"?Value="Center"/><Setter?Property="HorizontalAlignment"?Value="Center"/></Style><Style?TargetType="Border"><Setter?Property="Margin"?Value="1"/></Style></wpfdev:SixGirdView.Resources><MediaElement?x:Name="MyMediaElement"?Loaded="MyMediaElement_Loaded"MediaEnded="MyMediaElement_MediaEnded"/><Border?Background="#282C34"><wpfdev:SmallPanel><TextBlock?Text="信號源1"/><Border?Background="{DynamicResource?PrimaryNormalSolidColorBrush}"VerticalAlignment="Top"HorizontalAlignment="Right"Padding="10,4"CornerRadius="3"><TextBlock?Text="HD"/></Border></wpfdev:SmallPanel></Border><Border?Background="#282C34"><TextBlock?Text="無信號"/></Border><Border?Background="#282C34"><TextBlock?Text="無信號"/></Border><Border?Background="#282C34"><TextBlock?Text="無信號"/></Border><Border?Background="#282C34"><TextBlock?Text="無信號"/></Border></wpfdev:SixGirdView><controls:CodeViewer.SourceCodes><controls:SourceCodeModel?CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/SixGirdViewExample.xaml"?CodeType="Xaml"/><controls:SourceCodeModel?CodeSource="/WPFDevelopers.SamplesCode;component/ExampleViews/SixGirdViewExample.xaml.cs"?CodeType="CSharp"/></controls:CodeViewer.SourceCodes></controls:CodeViewer>
</UserControl>

3)新建 SixGirdViewExample.xaml.cs 代碼如下:

using?System;
using?System.IO;
using?System.Windows;
using?System.Windows.Controls;namespace?WPFDevelopers.Samples.ExampleViews
{///?<summary>///?NineGridViewExample.xaml?的交互邏輯///?</summary>public?partial?class?SixGirdViewExample?:?UserControl{public?SixGirdViewExample(){InitializeComponent();}private?void?MyMediaElement_Loaded(object?sender,?RoutedEventArgs?e){var?path?=?"E:\\DCLI6K5UIAEmH9R.mp4";if?(File.Exists(path))MyMediaElement.Source?=?new?Uri(path);}private?void?MyMediaElement_MediaEnded(object?sender,?RoutedEventArgs?e){MyMediaElement.Position?=?new?TimeSpan(0);}}
}
95772ebcf04af6a9d65e4c8716fc4c7b.gif

參考資料

[1]

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

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

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

相關文章

漢三水屬國(北地屬國、安定屬國)

漢三水屬國&#xff08;北地屬國、安定屬國&#xff09; 兩漢&#xff08;西漢、東漢&#xff09;400年中&#xff0c;由于各種原因&#xff0c;經常有成批的匈奴歸附漢朝&#xff0c;兩漢政府對他們采取了較為妥善的安置政策&#xff0c;其中最主要的措施是為他們設立專門的居…

《爆發》作者:大數據領域將有新贏家

本文講的是《爆發》作者&#xff1a;大數據領域將有新贏家,全球復雜網絡研究專家日前到訪中國&#xff0c;為其新作《爆發》作宣傳。他在接受國內媒體采訪時表示&#xff0c;未來可能有新公司取代谷歌、Facebook等公司&#xff0c;成為大數據領域的贏家。 《爆發》一書是一本討…

chromebook刷機_如何獲取Android應用以查看Chromebook上的外部存儲

chromebook刷機Android apps are a great way to expand the sometimes limited capabilities of Chromebooks, but they can be a problem if you store most of your data on an external medium—like an SD card, for example. Android應用程序是擴展Chromebook有時有限功能…

Stream流與Lambda表達式(四) 自定義收集器

一、自定義SetCustomCollector收集器 package com.java.design.Stream.CustomCollector;import java.util.*; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; import java.util.function.Function; import java.util.function.Supplier; im…

ModelState.IsValid忽略型別的檢查錯誤

Web Api在Int或DateTime如果傳空值的話會自動幫忙設預設值&#xff0c;但是在ModelState.IsValid的時候&#xff0c;卻會出現型別上的錯誤.解決方式把Model改成正確&#xff0c;也就是預設允許可以為nullpublic class DemoModel { …

android 指紋添加_如何將手勢添加到Android手機的指紋掃描儀

android 指紋添加So you have a shiny new Android phone, equipped with a security-friendly fingerprint scanner. Congratulations! But did you know that, while useful on its own, you can actually make the fingerprint scanner do more than just unlock your phone…

關于前端性能優化

常用的優化有兩部分 第一&#xff1a;面向內容的優化 減少 HTTP 請求減少 DNS 查找避免重定向使用 Ajax 緩存延遲載入組件預先載入組件減少 DOM 元素數量切分組件到多個域最小化 iframe 的數量不要出現http 404 錯誤第二&#xff1a;面向 Server 縮小 Cookie針對 Web 組件使用域…

前端工程化:圍繞Jenkins打造工作流的過程

背景 1年前入職時&#xff0c;公司前端部門的靜態代碼部署都是用ftp工具拖拽部署&#xff0c;沒有記錄&#xff0c;沒有關聯&#xff0c;經常造成許多困擾的問題&#xff0c; 比如&#xff1a;今天有沒有其他人在我要部署的路徑上工作&#xff1f;我的代碼為啥被蓋掉了&#xf…

業務id轉密文短鏈的一種實現思路

業務場景&#xff1a; 買家通過電商app下單后&#xff0c;會受到一條短信&#xff0c;短信內容中包括改訂單詳情頁面的h5地址連接&#xff0c;因為是出現在短信中&#xff0c;所以對連接有要求&#xff1a;1.盡量短&#xff1b;2.安全性考慮&#xff0c;訂單在數據庫中對應的自…

百度高管:問心無愧

1月23日下午消息&#xff0c;今天下午&#xff0c;百度召開百家號2019內容創作者盛典&#xff0c;百度副總裁沈抖出席并發布演講。 就在前一天&#xff0c;一篇名為《搜索引擎百度已死》的文章刷屏&#xff0c;文中提到百度搜索有一半以上會指向百度自家產品&#xff0c;尤其百…

Vuex 學習筆記

Vuex 是什么&#xff1f; Vuex 是一個專為 Vue.js應用程序開發的狀態管理模式。由于SPA應用的模塊化&#xff0c;每個組件都有它各自的數據&#xff08;state&#xff09;、視圖&#xff08;view&#xff09;和方法&#xff08;actions&#xff09;&#xff0c;當項目內容越來越…

xdf文檔怎么轉換為pdf_如何將PDF文件和圖像轉換為Google文檔文檔

xdf文檔怎么轉換為pdfYou probably know you can create and edit documents with Google Docs, but you can edit more than just .doc files. Google Drive can also convert any PDF, JPG, PNG, or GIF into a document with fully editable text. Here’s how. 您可能知道可…

在現代 Windows 上使用經典 Windows 2000、XP、Vista 任務欄

你好&#xff0c;這里是 Dotnet 工具箱&#xff0c;定期分享 Dotnet 有趣&#xff0c;實用的工具和組件&#xff0c;希望對您有用&#xff01;前言您第一次使用的 Windows 是哪個版本的&#xff1f;我最早使用的 Windows XP&#xff0c;然后再經過 XP、7、8/8.1 、Windows 10&a…

oracle sys可以登錄,system權限不足,解決方法

今天在自己電腦上安裝了oracle 11g&#xff0c;安裝成功后發現 sys 可以正常登錄。system 無法登錄&#xff0c;顯示 ORA-01031: insufficient privileges(權限不足) select * from v$pwfile_users; 查看有sysdba權限的用戶 grant sysdba to system; 給system 授權sysdba權限…

airdroid黑屏_如何使用AirDroid從PC控制Android設備

airdroid黑屏AirDroid for Android replaces your USB cable for connecting to your PC. Transfer files back and forth, send text messages, play music, view your photos, and manage applications using a web browser or a desktop client. 適用于Android的AirDroid取代…

分析java程序

2019獨角獸企業重金招聘Python工程師標準>>> 最近公司的一個賬單推送的服務&#xff0c;發現有延遲。我排查的時候發現&#xff0c;有一個程序日志不動了&#xff08;采用消息隊列&#xff0c;部署了兩臺服務器來負載均衡&#xff09;。 網上說&#xff1a; jstack …

環境部署(九):linux下安裝python+chrome+Xvfb

在基于selenium進行的UI自動化測試中&#xff0c;開發調試環境一般都是windows操作系統。完成后需要部署到專門的測試環境。 如要要部署到linux環境的服務器&#xff08;阿里云、騰訊云&#xff09;執行&#xff0c;那么測試腳本也需要對應的瀏覽器支持&#xff0c; 才能正常進…

地理圍欄_什么是“地理圍欄”?

地理圍欄The term is popping up more frequently in news articles, appearing in product manuals, and highlighted as a feature in tons of mobile applications, but what exactly is geofencing? Read on as we explain what it is, why it’s appearing in more produ…

219. 單頁應用 會話管理(session、cookie、jwt)

原文鏈接&#xff1a;https://github.com/ly525/blog... 關鍵字&#xff1a;http-only, cookie,sessionid, vue-router, react-router, 安全&#xff0c;localStorage, jwt 需求描述 內部管理平臺&#xff0c;需要用戶登錄之后才能訪問。現在將 該平臺地址&#xff08;www.xxx.…

(原+譯)使用numpy.savez保存字典后讀取的問題

轉載請注明出處&#xff1a; http://www.cnblogs.com/darkknightzh/p/7608928.html 參考網址; https://stackoverflow.com/questions/22315595/saving-dictionary-of-header-information-using-numpy-savez python中&#xff0c;使用pickle保存變量時&#xff0c;如果變量過大&…