Image inside sliding CheckBox in XAML

2019-09-10 08:13发布

I have the following style that I got from [Here]https://stackoverflow.com/a/5349484/3260977) and I have added an image to the Border with x:Name = "slider". I want to reuse this control and want to be able to assign the image source for each control without having to duplicate the style for each control. Here is my style:

    <Style x:Key="OrangeSwitchStyle" TargetType="{x:Type CheckBox}">
    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}" />
    <Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
                <ControlTemplate.Resources>
                    <Storyboard x:Key="OnChecking">
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
                            <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="53" />
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                    <Storyboard x:Key="OnUnchecking">
                        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="slider" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
                            <SplineDoubleKeyFrame KeyTime="00:00:00.1000000" Value="0" />
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
                </ControlTemplate.Resources>
                <DockPanel x:Name="dockPanel">
                    <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" 
                                      Content="{TemplateBinding Content}" 
                                      ContentStringFormat="{TemplateBinding ContentStringFormat}" 
                                      ContentTemplate="{TemplateBinding ContentTemplate}" 
                                      RecognizesAccessKey="True" 
                                      VerticalAlignment="Center"
                                      DockPanel.Dock="Top"/>
                    <Grid DockPanel.Dock="Bottom">
                        <Border x:Name="BackgroundBorder" 
                                BorderBrush="#FF939393" 
                                BorderThickness="1" 
                                CornerRadius="3" 
                                Height="27" 
                                Width="94">
                            <Border.Background>
                                <LinearGradientBrush StartPoint="0,0" EndPoint="0,1">
                                    <GradientStop Color="#FFB5B5B5" Offset="0" />
                                    <GradientStop Color="#FFDEDEDE" Offset="0.1" />
                                    <GradientStop Color="#FFEEEEEE" Offset="0.5" />
                                    <GradientStop Color="#FFFAFAFA" Offset="0.5" />
                                    <GradientStop Color="#FFFEFEFE" Offset="1" />
                                </LinearGradientBrush>
                            </Border.Background>
                            <Grid>
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition />
                                    <ColumnDefinition />
                                </Grid.ColumnDefinitions>
                                <Ellipse x:Name="Off" 
                                         Width="14" 
                                         Height="14" 
                                         Stroke="#FF7A7A7A" 
                                         StrokeThickness="2" 
                                         Grid.Column="1" 
                                         HorizontalAlignment="Center" 
                                         VerticalAlignment="Center" />
                                <Line x:Name="On" 
                                      X1="0" 
                                      Y1="0" 
                                      X2="0" 
                                      Y2="14" 
                                      Stroke="#FF7A7A7A" 
                                      StrokeThickness="2" 
                                      Grid.Column="0" 
                                      HorizontalAlignment="Center" 
                                      VerticalAlignment="Center" />
                            </Grid>
                        </Border>
                        <Border BorderBrush="#FF939393" 
                                HorizontalAlignment="Left"
                                x:Name="slider" 
                                Width="41" 
                                Height="27" 
                                BorderThickness="1" 
                                CornerRadius="3" 
                                RenderTransformOrigin="0.5,0.5" 
                                Margin="0">
                            <Image Source="Resources/Capture.png" Width="30" Height="30"></Image>
                            <Border.RenderTransform>
                                <TransformGroup>
                                    <ScaleTransform ScaleX="1" ScaleY="1" />
                                    <SkewTransform AngleX="0" AngleY="0" />
                                    <RotateTransform Angle="0" />
                                    <TranslateTransform X="0" Y="0" />
                                </TransformGroup>
                            </Border.RenderTransform>
                            <Border.Background>
                                <LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
                                    <GradientStop Color="#FFF0F0F0" Offset="0" />
                                    <GradientStop Color="#FFCDCDCD" Offset="0.1" />
                                    <GradientStop Color="#FFFBFBFB" Offset="1" />
                                </LinearGradientBrush>
                            </Border.Background>
                        </Border>
                    </Grid>
                </DockPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="True">
                        <Trigger.ExitActions>
                            <BeginStoryboard Storyboard="{StaticResource OnUnchecking}" x:Name="OnUnchecking_BeginStoryboard" />
                        </Trigger.ExitActions>
                        <Trigger.EnterActions>
                            <BeginStoryboard Storyboard="{StaticResource OnChecking}" x:Name="OnChecking_BeginStoryboard" />
                        </Trigger.EnterActions>
                        <Setter TargetName="On" Property="Stroke" Value="White" />
                        <Setter TargetName="Off" Property="Stroke" Value="White" />
                        <!-- Change Orange or Blue color here -->
                        <Setter TargetName="BackgroundBorder" Property="Background" Value="{StaticResource CheckedOrange}" />
                        <Setter TargetName="BackgroundBorder" Property="BorderBrush" Value="{StaticResource CheckedOrangeBorder}" />
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="False">
                        <!-- ToDo: Add Style for Isenabled == False -->
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

And want to change the source for each control...

Any ideas?

Thanks!

2条回答
SAY GOODBYE
2楼-- · 2019-09-10 08:18

there are three solutions for your problem

  1. create New Class that is inherited from CheckBox Control and put new DependencyProperty There Called for example ImageString and then Convert Binding String into BitmapImage like this:
 public class newCheckBox : CheckBox
    {
       // add ImageString dependency property and change it to BitmaoImage
    }

and then put your CheckBox Template and Bind the Source of Image To new ImageString DependencyProperty.

  1. or you can use DynamicResource like this:
<ControlTemplate TargetType="CheckBox">
    <Border>
        <StackPanel Orientation="Horizontal">
            <Image Source="{DynamicResource ResourceKey=Img}" Height="100" Width="100" Margin="5"></Image>
            <ContentPresenter/>
        </StackPanel>
    </Border>
</ControlTemplate>

and when defining new CheckBox use this:

<CheckBox Content="myCheckBox">
    <CheckBox.Resources>
        <ImageSource x:Key="Img">your Uri Image</ImageSource>
    </CheckBox.Resources>
</CheckBox>
  1. 3d solution is create new TagConverter that take Tag Property and Convert it to BitmapImage like this:
<Style TargetType="CheckBox">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="CheckBox">
                <Grid>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="50"></ColumnDefinition>
                        <ColumnDefinition Width="50"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <Image Stretch="Fill" Source="{TemplateBinding Tag, Converter={StaticResource TagConverter}}"></Image>
                    <ContentPresenter Grid.Column="1"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Converter Code is :

public class TagConverter: IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return new BitmapImage(new Uri(value.ToString(),UriKind.RelativeOrAbsolute));
    }
}

and put your Image path in CheckBox Tag Property

<CheckBox Tag="1.png" Content="MyCheck 1"></CheckBox>
查看更多
Root(大扎)
3楼-- · 2019-09-10 08:31

Using Datatemplate and ContentTemplate we can reuse this style.Please see commented text. I have removed <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}" ></ContentPresenter> and added <ContentControl ContentTemplate="{TemplateBinding ContentTemplate}" Width="30" Height="30"/> instead of Image control as image doent have ContentTemplate property.

<Window.Resources>
    <DataTemplate x:Key="Image1">
        <Image Source="darblue_tab.png"></Image>
    </DataTemplate>

    <Style TargetType="{x:Type CheckBox}">
        .......
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type CheckBox}"> 
                    ......
                    <DockPanel x:Name="dockPanel">

                        <!--Remove  ContentTemplate="{TemplateBinding ContentTemplate}" from ContentPresenter-->

                        <ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding Content}" ContentStringFormat="{TemplateBinding ContentStringFormat}" RecognizesAccessKey="True" VerticalAlignment="Center" DockPanel.Dock="Top"/>
                        <Grid DockPanel.Dock="Bottom">
                            ......
                            <Border BorderBrush="#FF939393" HorizontalAlignment="Left" x:Name="slider" Width="41" Height="27" BorderThickness="1" CornerRadius="3" RenderTransformOrigin="0.5,0.5" Margin="0">
                                <!--Use ContentControl control as image doesn't have content,ControlTemplate and ContentTemplate property.  -->
                                <ContentControl  ContentTemplate="{TemplateBinding ContentTemplate}" Width="30" Height="30"/>
                            </Border>
                            .......
                        </Grid>
                    </DockPanel>  
                    ......
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>


<CheckBox Content="Checkbox" ContentTemplate="{StaticResource Image1}" ></CheckBox>
查看更多
登录 后发表回答