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>
那么今天就这样~