1. 程式人生 > >WPF 動態新增按鈕以及樣式字典的引用(Style introduction)

WPF 動態新增按鈕以及樣式字典的引用(Style introduction)

  我們想要達到的結果是,繫結多個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>

我把縮排的截圖發上來,更直觀。

&n