WPF 動態添加控制項以及樣式字典的引用(Style introduction)
- 2019 年 10 月 3 日
- 筆記
我們想要達到的結果是,綁定多個Checkbox然後我們還可以獲取它是否被選中,其實很簡單,我們只要找到那幾個關鍵的對象就可以了。
下面是Ui,其中定義了一個WrapPanel來存放CheckBox,還有兩個按鈕,用於測試相關功能。
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfApplication1" mc:Ignorable="d" Title="MainWindow" Height="350" Width="525"> <Grid Name="div" > <StackPanel Margin="0,50,0,0" Orientation="Horizontal" HorizontalAlignment="Center"> <StackPanel> <Button Content="動態添加多個checkbox控制項" Height="20" Padding="15,1,15,2" x:Name="btnAdd" Click="btnAdd_Click"></Button> </StackPanel> </StackPanel> <ScrollViewer ScrollViewer.VerticalScrollBarVisibility="Auto" Height="150"> <Border BorderBrush="#797979" BorderThickness="1" Margin="5,0,5,5"> <WrapPanel x:Name="addCheckbox"/> </Border> </ScrollViewer> <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="37,261,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/> <Button x:Name="button1" Content="Button" HorizontalAlignment="Left" Margin="379,50,0,0" VerticalAlignment="Top" Width="75" Click="button1_Click"/> </Grid> </Window>
在動態添加Checkbox中我們定義了一個CheckBox數組,此後又實例化了ThickNess對象,它是用於描述矩形周圍的粗細,然後我們又循環了數組的長度來進行添加(對其中name為addCheckbox的控制項),至此,checkbox已動態添加。
那如何刪除呢?我們依舊需要獲取那個名為addCheckbox的控制項的兒子們(Children)來進行remove。請看以下程式碼片段。
private void button1_Click(object sender, RoutedEventArgs e) { for (int i = 0; i < addCheckbox.Children.Count;) { this.addCheckbox.Children.Remove(addCheckbox.Children[i]); } }
循環其中的值也是非常的簡單,因為我們在上面綁定的時候,已經給它的Content或者是DataContext都賦值了,所以我們只要獲取就ok了。
private void button_Click(object sender, RoutedEventArgs e) { foreach (UIElement item in addCheckbox.Children) { if (item is CheckBox) { CheckBox checkbox = (item as CheckBox); if (checkbox.IsChecked == true) { MessageBox.Show(checkbox.Content.ToString()); } } } }
最後生成出來的效果是這樣的,是不是非常丑,那我教你如何進行簡單的美化。
在我們添加checkbox的時候有兩種引入方式,一種是 checkbox.Style = Resources[“NoticeBox“] as Style; 另一種的話是 Style style = (Style)this.FindResource(“NoticeButton“); 那兩者有什麼區別呢?
第一個是必須將資源文件引用到當前頁面,第二種的是在App.xaml進行查找不包括app.xaml中引入的(外部的資源文件)。下面我們寫一個CheckBox樣式在app,xaml中。
<Application x:Class="WpfApplication1.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1" StartupUri="MainWindow.xaml"> <Application.Resources> <Style x:Key="CheckBoxSwitchStyle" TargetType="CheckBox"> <Setter Property="IsChecked" Value="False"/> <Setter Property="Cursor" Value="Hand"/> <Setter Property="FontFamily" Value="/MESToolIntegration;component/Fonts/#iconfont"/> <Setter Property="Background" Value="#FFFFFF"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="CheckBox"> <Border Width="54" Name="CheckTrueBG" Height="22" BorderThickness="1" Background="#FFFFFF" CornerRadius="10" BorderBrush="#ACACAC" > <Grid> <Border BorderThickness="1" Background="#ACACAC" x:Name="border" Width="20" Height="20" CornerRadius="9" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0" > <Border.RenderTransform> <TranslateTransform X="1"/> </Border.RenderTransform> </Border> <TextBlock x:Name="txt" Text="{TemplateBinding Content}" FontFamily="iconfont" FontSize="{TemplateBinding FontSize}" Margin="6.996,2.798,0,2.798" VerticalAlignment="Stretch" Foreground="#ACACAC" HorizontalAlignment="Left" > <TextBlock.RenderTransform> <TranslateTransform X="17"></TranslateTransform> </TextBlock.RenderTransform> </TextBlock> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="true"> <Setter Property="Background" TargetName="CheckTrueBG" Value="#5FB878"/> <Setter Property="Foreground" TargetName="txt" Value="#FFFFFF"/> <Setter Property="Background" TargetName="border" Value="#FFFFFF"/> <Setter Property="Text" TargetName="txt" Value="{Binding Tag,RelativeSource={RelativeSource TemplatedParent}}"/> <Trigger.EnterActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" To="32" Duration="00:00:0.2"/> <DoubleAnimation Storyboard.TargetName="txt" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" To="0" Duration="00:00:0.2"/> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> <Trigger.ExitActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" To="0" Duration="00:00:0.2"/> <DoubleAnimation Storyboard.TargetName="txt" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" To="17" Duration="00:00:0.2"/> </Storyboard> </BeginStoryboard> </Trigger.ExitActions> </Trigger> <Trigger Property="IsChecked" Value="False"> <Setter Property="Text" TargetName="txt" Value="{Binding Content,RelativeSource={RelativeSource TemplatedParent}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </Application.Resources> </Application>
就這樣我們在生成CheckBox中進行配置,程式碼如下。
private void btnAdd_Click(object sender, RoutedEventArgs e) { int num = 6; CheckBox[] check = new CheckBox[num]; Thickness th = new Thickness(); th.Bottom = 10; th.Left = 10; th.Right = 10; th.Top = 10; for (int i = 0; i < check.Length; i++) { check[i] = new CheckBox(); //設置checkbox屬性 check[i].Margin = th; check[i].Content = i + 1; check[i].Name = "heheda"; check[i].DataContext = "asdas"; check[i].Style = (Style)this.FindResource("CheckBoxSwitchStyle"); this.addCheckbox.Children.Add(check[i]); } }
啟動頁面我們可以發現引入成功了。
不難發現,看一下程式碼,我們如何還想寫別的樣式,這個時候應該怎麼辦?難道還要往app.xaml里寫?這就非常噁心了,所以我們採用引入的方式,這和css有點像!新建一個資源字典。
在其中寫入寫入以下樣式。
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:WpfApplication1"> <Style x:Key="BtnInfoStyle" TargetType="Button"> <Setter Property="Width" Value="70"/> <Setter Property="Height" Value="25"/> <Setter Property="Foreground" Value="White"/> <Setter Property="BorderThickness" Value="0"/> <Setter Property="Background" Value="#43a9c7"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <Border x:Name="border" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" SnapsToDevicePixels="True"> <TextBlock Text="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"/> </Border> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter TargetName="border" Property="Background" Value="#2f96b4"/> </Trigger> <Trigger Property="IsPressed" Value="True"> <Setter TargetName="border" Property="Background" Value="#2a89a4"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary>
然後在app.xaml中進行引用,這裡需要注意是,有可能我們的style和外部字典都放進去了,它們的關係是style其實也是一個字典,然後就變成了這樣。
<Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Dictionary1.xaml"/> </ResourceDictionary.MergedDictionaries> <Style x:Key="CheckBoxSwitchStyle" TargetType="CheckBox"> <Setter Property="IsChecked" Value="False"/> <Setter Property="Cursor" Value="Hand"/> <Setter Property="FontFamily" Value="/MESToolIntegration;component/Fonts/#iconfont"/> <Setter Property="Background" Value="#FFFFFF"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="CheckBox"> <Border Width="54" Name="CheckTrueBG" Height="22" BorderThickness="1" Background="#FFFFFF" CornerRadius="10" BorderBrush="#ACACAC" > <Grid> <Border BorderThickness="1" Background="#ACACAC" x:Name="border" Width="20" Height="20" CornerRadius="9" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0" > <Border.RenderTransform> <TranslateTransform X="1"/> </Border.RenderTransform> </Border> <TextBlock x:Name="txt" Text="{TemplateBinding Content}" FontFamily="iconfont" FontSize="{TemplateBinding FontSize}" Margin="6.996,2.798,0,2.798" VerticalAlignment="Stretch" Foreground="#ACACAC" HorizontalAlignment="Left" > <TextBlock.RenderTransform> <TranslateTransform X="17"></TranslateTransform> </TextBlock.RenderTransform> </TextBlock> </Grid> </Border> <ControlTemplate.Triggers> <Trigger Property="IsChecked" Value="true"> <Setter Property="Background" TargetName="CheckTrueBG" Value="#5FB878"/> <Setter Property="Foreground" TargetName="txt" Value="#FFFFFF"/> <Setter Property="Background" TargetName="border" Value="#FFFFFF"/> <Setter Property="Text" TargetName="txt" Value="{Binding Tag,RelativeSource={RelativeSource TemplatedParent}}"/> <Trigger.EnterActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" To="32" Duration="00:00:0.2"/> <DoubleAnimation Storyboard.TargetName="txt" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" To="0" Duration="00:00:0.2"/> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> <Trigger.ExitActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetName="border" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" To="0" Duration="00:00:0.2"/> <DoubleAnimation Storyboard.TargetName="txt" Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)" To="17" Duration="00:00:0.2"/> </Storyboard> </BeginStoryboard> </Trigger.ExitActions> </Trigger> <Trigger Property="IsChecked" Value="False"> <Setter Property="Text" TargetName="txt" Value="{Binding Content,RelativeSource={RelativeSource TemplatedParent}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style> </ResourceDictionary> </Application.Resources>
我把縮進的截圖發上來,更直觀。
在其中還有內嵌的樣式,可以這麼寫,如果是page的話你就 <Page.Resources> ,如果是windows的話那就Wndows,當然如果需要頁面引入字典的話你可以這麼做。
<Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Style/test.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources>
那麼今天就這樣~