button 樣式_WPF 讓一組 Button 實現 RadioButton 的當前樣式效果
技術標籤:button 樣式button按鈕onclick觸發不了button按鈕樣式button按鈕的屬性設定button樣式button點選後出現的邊框
WPF讓一組 Button 實現RadioButton的當前樣式效果
—— 獨立觀察員2020 年 6 月 19 日
概述:本文通過 WPF 的資料觸發器(DataTrigger) 和多重繫結(MultiBinding),在一組普通按鈕(Button) 上實現了像單選按鈕(RadioButton) 那樣的,同一時間只有一個按鈕具有當前樣式(本文演示的是背景顏色)的效果。
需求起因:公司專案中有個 WPF 專案,有個介面下方有一塊顯示當前資訊的區域,並且有幾個按鈕,意圖是點選之後可以切換為另一區域的資訊。由於到目前為止,業務中都還只有一個區域,所以之前同事就沒寫這切換的邏輯。經過本人的不懈努力,切換邏輯寫好了,就差切換後按鈕樣式的轉移了,如下圖。
這種需求本來最好是直接使用 RadioButton,然後更改顯示模板的。由於內部還有其它邏輯,改起來也沒有那麼輕鬆,加上之前觸發器用得比較少,多重繫結也沒怎麼用過,正好可以藉此機會練練手,所以就還是基於普通按鈕來實現這個需求。
首先給出幾個按鈕的程式碼:
<Button Command="{Binding CommandEntranceSwitch}" CommandParameter="1" Tag="{Binding LeftEntranceSelected.Tag}" Style="{DynamicResource RadioStyleButton}"/>
<Button Command="{Binding CommandEntranceSwitch}" CommandParameter="2" Tag="{Binding LeftEntranceSelected.Tag}" Style="{DynamicResource RadioStyleButton}"/>
<Button Command="{Binding CommandEntranceSwitch}" CommandParameter="3" Tag="{Binding LeftEntranceSelected.Tag}" Style="{StaticResource BorderStyleButton}"/>
Command 綁定了按鈕的命令,用於切換當前需要顯示的資料(即後面的 LeftEntranceSelected ),命令的程式碼與本文關係不大,就不展示了;
CommandParameter 是命令的引數,也就是作為區分按鈕的編號;
Tag 綁定了當前選中資訊的 Tag 屬性,用於與按鈕編號進行比較,三個按鈕的 Tag 值是一樣的;
Style 就是本次添加了觸發器的樣式,可以看到第三個按鈕還是原來的樣式,這是我故意給出的錯誤示範,因為之前忘了元素上的樣式優先順序更高,以為外面的 Style 指定了 TargetType 就行,這裡也給大家提個醒。還有一個坑就是,要使用 DynamicResource,不能使用 StaticResource,不然沒有反應。
然後就是本次新增的樣式(樣式裡有資料觸發器,觸發器裡有多重繫結):
<Grid.Resources>
<Style TargetType="Button" BasedOn="{StaticResource BorderStyleButton}" x:Key="RadioStyleButton">{StaticResource EqualConverter}">{RelativeSource Self}" Path="Tag">{RelativeSource Self}" Path="CommandParameter">"Background" Value="#4BEF9E"/>
Style>
Grid.Resources>
可以看到,此樣式目標為 Button,基於原樣式 BorderStyleButton,取名為 RadioStyleButton。DataTriggers 的 Value 設為 true,表明 Binding 中計算的值為 true 時,設定 Setter 中指定的樣式(此處為背景色)。那麼關鍵就是 Binding 中如何計算了。
此處使用了多重繫結(MultiBinding),綁定了每個應用了該樣式的 Button 元素上的 Tag 和 CommandParameter,因為每個 Button 自己的 CommandParameter 是確定的,而 Tag 隨著選中項變化,當兩者相等,說明自己被選中了,隨即被設定上當前樣式。
那麼怎麼判斷兩者是否相等呢?答案就是使用 MultiBinding 的轉換器(Converter)EqualConverter:
<converters:EqualConverter x:Key="EqualConverter">converters:EqualConverter>
轉換器程式碼為:
///
/// [dlgcy]相等比較器(判斷給定的資料的字串形式是否都相等)
///
public class EqualConverter:IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
if (values == null || values.Length == 0)
throw new ArgumentNullException(nameof(values), "values can not be null or empty");
return values.All(x => x+"" == values[0]+"");
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
return null;
}
}
最終效果為:
希望大家多多討論,不吝賜教。