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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

让 WPF 的 RadioButton 支持再次点击取消选中的功能

發布時間:2023/12/4 asp.net 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 让 WPF 的 RadioButton 支持再次点击取消选中的功能 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

讓 WPF 的 RadioButton 支持再次點擊取消選中的功能

目錄

讓 WPF 的 RadioButton 支持再次點擊取消選中的功能

零、前言

一、方法一:后臺直接處理

二、方法二:提取為自定義控件(用戶控件)

三、方法三:附加行為法

獨立觀察員 2022 年 01 月 16 日

零、前言

眾所周知,RadioButton?是一種單選框,一般是放置好幾個在同一面板中以組成一組;使用時,初始時可能一個都沒被選中,或者是設置了一個默認選中項;然后,用戶可以在這一組單選框中切換選擇其中一個,不能多選,也不能取消選中(也就是不能重新回到一個都沒選的狀態)。

最近公司軟件中有個界面,UI 給出的樣式就是單選框的形式,所以就使用了一組?RadioButton?來實現,初始是一個都沒選,之后用戶可以在其中選擇一項。可是后來需求說選中的項再次點擊需要取消選中,摔!這個功能 RadioButton 是辦不到的,CheckBox 是可以的,不過如果換成 CheckBox,一方面樣式要改,另一方面,只能選擇一項這個需求也要寫代碼實現(CheckBox 好像可以設置為單選?算了,不要在意這些細節),所以還是找找方法,看能不能讓 RadioButton 支持取消選中吧。

一、方法一:后臺直接處理

網上找到的方法就是在后臺新增一個 bool 變量,用來記錄上次(或者說點擊前)RadioButton 是選中還是未選中,然后在點擊事件中進行判斷處理:

來看看效果吧(動圖):

上面的動圖先演示了 RadioButton 默認是不支持取消選中的;然后演示了通過上面代碼實現的支持取消選中的 RadioButton。

這樣確實是可以的,但是只適用于只有單個 RadioButton 的情況,因為如果有好幾個 RadioButton,那么就要為每個 RadioButton 新建一個布爾變量以及一個點擊事件方法,最多是把事件方法整合一下,總之是很奇怪的。

當然,這個戰略(引入一個布爾變量來記錄上次的選擇情況)是沒問題,只不過戰術(直接在后臺處理)有點問題。那么我們使用這個戰略的話,還能形成什么戰術呢?大致可以想到兩種方法,接下來容我一一道來。

二、方法二:提取為自定義控件(用戶控件)

我們新建一個名為 RadioButtonUncheck 的用戶控件(UserControl),將繼承關系改為 RadioButton,并把上一節所示的處理邏輯添加進去:

前臺直接改為實例化一個 RadioButton 即可:

然后在界面上使用這個用戶控件:

看看效果(動圖):

很明顯,有一些 Bug,這是為什么呢?原因就是,我們新建的那個用來記錄上次選中狀態的變量,在用戶選中其它項,同時?WPF?框架自動取消選中本項時,沒有進行記錄。

所以我們需要在 Checked 和 Unchecked 這兩個事件中分別對?_lastChecked 進行相應的賦值:

然后,由于觸發了 Click 事件后(也有可能是 PreviewMouseDown 后 Click 前的某個事件,比如 PreviewMouseUp),WPF 框架(或者說是 RadioButton 內部)就會把 IsChecked 設為 true(這就是前面的代碼中需要另外新建變量來判斷的原因),所以需要換為 PreviewMouseDown 事件,并在處理完成后調用 “e.Handled = true;” 阻止事件繼續傳遞:

現在,當 RadioButtonUncheck 控件通過點擊由未選切換為選中時,事件執行順序為 PreviewMouseDown--Checked:

或:

而由選中切換為未選時,事件執行順序為 PreviewMouseDown--Unchecked:

而如果沒有 “e.Handled = true;”,則由未選切換為選中時,事件執行順序如下:

或:

由選中切換為未選時(切換失敗),事件執行順序如下:

至此,用戶控件法圓滿完成任務(動圖):

完整代碼:

using System; using System.Windows; using System.Windows.Controls;namespace WPFPractice.UserControls {/// <summary>/// 支持點擊取消選中的 RadioButton;/// </summary>public partial class RadioButtonUncheck : RadioButton{/// <summary>/// 上次的選中狀態/// </summary>private bool _lastChecked;/// <summary>/// 內容字符串/// </summary>private string ContentStr => Content + "";public RadioButtonUncheck(){InitializeComponent();Click += RadioButtonUncheck_Click; ;PreviewMouseDown += RadioButtonUncheck_PreviewMouseDown; ;Checked += RadioButtonUncheck_Checked;Unchecked += RadioButtonUncheck_Unchecked;}/// <summary>/// 點擊事件處理方法/// </summary>private void RadioButtonUncheck_Click(object sender, RoutedEventArgs e){Console.WriteLine($"[{ContentStr}] 觸發 Click 事件 ");//SwitchStatus();}/// <summary>/// 鼠標按下事件處理方法/// </summary>private void RadioButtonUncheck_PreviewMouseDown(object sender, System.Windows.Input.MouseButtonEventArgs e){Console.WriteLine($"[{ContentStr}] 觸發 PreviewMouseDown 事件 ");SwitchStatus();e.Handled = true;}/// <summary>/// 切換狀態/// </summary>private void SwitchStatus(){if (_lastChecked){IsChecked = false;//_lastChecked = false;}else{IsChecked = true;//_lastChecked = true;}}/// <summary>/// 選中事件 處理方法/// </summary>private void RadioButtonUncheck_Checked(object sender, RoutedEventArgs e){Console.WriteLine($"[{ContentStr}] 觸發 Checked 事件 ");_lastChecked = true;}/// <summary>/// 取消選中事件 處理方法/// </summary>private void RadioButtonUncheck_Unchecked(object sender, RoutedEventArgs e){Console.WriteLine($"[{ContentStr}] 觸發 Unchecked 事件 ");_lastChecked = false;}} }

三、方法三:附加行為法

關于附加行為,是通過附加屬性來實現的,可以參考我之前的翻譯文章《【翻譯】WPF 中附加行為的介紹 Introduction to Attached Behaviors in WPF》:

在一個元素上設置一個附加屬性,那么你就可以從暴露這個附加屬性的類中獲得該元素的訪問。一旦那個類有權限訪問那個元素,它就能在其上掛鉤事件,響應這些事件的觸發,使該元素做出它本來不會做的事情。

下面直接進入正題,首先在一個新建類 RadioButtonAttached 中添加一個 bool 類型的附加屬性 IsCanUncheck,當其被設置為 true 時,會給設置的元素附加 PreviewMouseDown、Checked、Unchecked 三個事件,和上一節一樣:

注意,附加屬性還需要兩個包裝方法:

由于附加屬性的變動處理方法要求是靜態方法:

所以導致三個事件的處理方法也要是靜態方法,不然就會報錯:

進而導致之前引入成員變量?_lastChecked 的方式行不通了:

所以這個狀態存儲的地方需要另外尋找。對于這種情況,我經常使用的是元素的 Tag 屬性,這次也是這樣干的,也就是說使用單選框的 Tag 來存儲上次的選中與否狀態。

Checked 和 Unchecked 中還是換湯不換藥:

主要是 PreviewMouseDown 事件處理方法中,當第一次點擊,Tag 中還沒有存儲時,bool 會轉換失敗,所以 Tag 中應該存儲 true 供下次使用;而轉換成功則將轉換出的值(存在 lastChecked 變量中)取反存入 Tag 中供下次使用。(這樣看來兩種情況好像都可以直接使用 rb.Tag = !lastChecked; 哈哈,懶得改了)。之后就是依據 lastChecked 來決定(取反)IsChecked 的值:

完整代碼:

using System.Windows; using System.Windows.Controls;namespace WPFTemplateLib.Attached;/// <summary> /// RadioButton 附加屬性類 /// </summary> public class RadioButtonAttached : DependencyObject {#region IsCanUncheckpublic static bool GetIsCanUncheck(FrameworkElement item){return (bool)item.GetValue(IsCanUncheckProperty);}public static void SetIsCanUncheck(FrameworkElement item, bool value){item.SetValue(IsCanUncheckProperty, value);}/// <summary>/// 是否能取消選中 (啟用此功能會占用 Tag 屬性)/// </summary>public static readonly DependencyProperty IsCanUncheckProperty =DependencyProperty.RegisterAttached("IsCanUncheck",typeof(bool),typeof(RadioButtonAttached),new UIPropertyMetadata(false, OnIsCanUncheckChanged));static void OnIsCanUncheckChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e){FrameworkElement item = depObj as FrameworkElement;if (item == null)return;switch (depObj){case RadioButton radioButton:{if ((bool) e.NewValue){radioButton.PreviewMouseDown += RadioButton_PreviewMouseDown;radioButton.Checked += RadioButton_Checked;radioButton.Unchecked += RadioButton_Unchecked;}else{radioButton.PreviewMouseDown -= RadioButton_PreviewMouseDown;radioButton.Checked -= RadioButton_Checked;radioButton.Unchecked -= RadioButton_Unchecked;}break;}default:break;}}private static void RadioButton_Unchecked(object sender, RoutedEventArgs e){var rb = sender as RadioButton;if (rb == null){return;}rb.Tag = false;}private static void RadioButton_Checked(object sender, RoutedEventArgs e){var rb = sender as RadioButton;if (rb == null){return;}rb.Tag = true;}private static void RadioButton_PreviewMouseDown(object sender, RoutedEventArgs e){var rb = sender as RadioButton;if (rb == null){return;}// 使用 RadioButton 的 Tag 來存儲上次選中的狀態,之后可以從中獲取來進行判斷;bool parseSuccess = bool.TryParse(rb.Tag + "", out bool lastChecked);if (!parseSuccess){// 轉換失敗,說明是第一次點擊,也就是本次本勾選了,所以應該把 true 存起來;rb.Tag = true;}else{rb.Tag = !lastChecked;}if (lastChecked){rb.IsChecked = false;//lastChecked = false;}else{rb.IsChecked = true;//lastChecked = true;}e.Handled = true;}#endregion }

使用時只需要在普通 RadioButton 元素上加上這個附加屬性并將值置為 True 即可:

效果和上一節的一樣(實際上方法三是先寫成的),就不再演示了,來個全家福吧:

最后是源碼地址:https://gitee.com/dlgcy/DLGCY_WPFPractice/tree/Blog20220116?

WPF

WPF DataGrid 如何將被選中行帶到視野中

WPF 觸屏事件后觸發鼠標事件的問題及 DataGrid 誤觸問題

WPF DataGrid 通過自定義表頭模擬首行固定

WPF ComboBox 使用 ResourceBinding 動態綁定資源鍵并支持語言切換

【翻譯】WPF 中附加行為的介紹 Introduction to Attached Behaviors in WPF

WPF 使用 Expression Design 畫圖導出及使用 Path 畫圖

WPF?MVVM?彈框之等待框

解決 WPF 綁定集合后數據變動界面卻不更新的問題(使用 ObservableCollection)

WPF?消息框?TextBox?綁定新數據時讓光標和滾動條跳到最下面

真?WPF?按鈕拖動和調整大小

WPF?MVVM?模式下的彈窗

WPF?讓一組 Button 實現?RadioButton?的當前樣式效果

WPF?原生綁定和命令功能使用指南

WPF?用戶控件的自定義依賴屬性在?MVVM?模式下的使用備忘

在WPF的MVVM模式中使用OCX組件

總結

以上是生活随笔為你收集整理的让 WPF 的 RadioButton 支持再次点击取消选中的功能的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。