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>

那么今天就这样~