【问题标题】:Change Images on Custom CheckBox in WPF在 WPF 中更改自定义复选框上的图像
【发布时间】:2013-09-03 10:14:36
【问题描述】:

我已经创建了以下自定义CheckBox,它使用图像而不是CheckBox。但是,这很好用,我希望能够根据需要更改图像。理想情况下,我想使用应用程序资源Properties.Resources.SomeImage16(一个 .png 文件)。 XAML 是

<Style x:Key="styleCustomCheckBox" 
       TargetType="{x:Type CheckBox}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type CheckBox}">
                <StackPanel Orientation="Horizontal">
                    <Image x:Name="imageCheckBox" 
                           Width="16" 
                           Height="16" 
                           Source="F:\Camus\ResourceStudio\Graphics\Images\UnPinned16.png"/>
                    <ContentPresenter VerticalAlignment="Center"/>
                </StackPanel>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsChecked" Value="False">
                        <Setter TargetName="imageCheckBox" 
                                Property="Source" 
                                Value="F:\Camus\ResourceStudio\Graphics\Images\Pinned16.png"/>
                    </Trigger>
                    <Trigger Property="IsChecked" Value="True">
                        <Setter TargetName="imageCheckBox" 
                                Property="Source"
                                Value="F:\Camus\ResourceStudio\Graphics\Images\UnPinned16.png"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

通过实施

<ListBox SelectionMode="Single" >
    <StackPanel Orientation="Horizontal">
        <CheckBox Style="{StaticResource styleCustomCheckBox}" 
                  HorizontalAlignment="Left" 
                  VerticalAlignment="Center"
                  Margin="4,0,4,0"/>
        <TextBlock VerticalAlignment="Top" 
                   Text="SomeRecentDocument.resx"/>
    </StackPanel>
</ListBox>

如何在不创建新样式/模板的情况下更改用于自定义CheckBox 的图像(即更改固定/取消固定为勾号/十字等)?

感谢您的宝贵时间。

【问题讨论】:

  • 1 - 不要对所有内容都使用 PNG。 WPF不是winforms。尽可能使用矢量图形。 2 - 你可能想创建一些Attached Properties 并绑定到ControlTemplate 中。
  • 如果允许,那么 .NET 应用程序将可以访问任何驱动器。
  • 不清楚你在问什么......是关于根据复选框状态更改图像吗?如果是这样,使用触发器会起作用,但您已经有一些触发器......您尝试的解决方案不起作用,您需要帮助才能使其起作用吗?
  • @DeanK。我有一个工作自定义复选框控件,其中的图像固定/取消固定。我想知道当我使用控件时如何/是否可以更改这些状态​​的图像...
  • @HighCore 如何从我的 Expression Design .design 文件中获取矢量图像?我可以导出到 XAML,但是某些图像的导出结果很复杂,并且由很多层组成...

标签: c# wpf checkbox


【解决方案1】:

正如已经提到的@HighCore 需要使用矢量图形的能力。在这种情况下,要使用Path,其中Data要指定在其上绘制对象的坐标(MSDN)。

优点:

  • 不要存储在文件中,体积更小

  • 动态改变颜色、大小和整体形状

缺点(在我看来):

  • 您无法始终为Path 找到正确的Data

关于减号:有特殊的网站 (www.modernuiicons.com) 和实用程序可将图像转换为 Data

使用Path改变CheckBox的样式:

Style

<Style x:Key="styleCustomCheckBox" TargetType="{x:Type CheckBox}">
        <Setter Property="FontFamily" Value="Verdana" />
        <Setter Property="FontSize" Value="14" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type CheckBox}">
                    <StackPanel Orientation="Horizontal">
                        <Path x:Name="MyPin" Width="18" Height="18" Stretch="Fill" Fill="#FF000000"
                              Data="F1 M 56.1355,32.5475L 43.4466,19.8526C 42.7886,20.4988 42.298,21.2123 41.9749,21.9932C 41.6519,22.7741 41.4903,23.5729 41.4903,24.3895C 41.4903,25.1942 41.6529,25.987 41.9779,26.7679L 34.0577,34.6821C 33.3918,34.3372 32.6991,34.0776 31.9796,33.9032C 31.2601,33.7288 30.5298,33.6415 29.7885,33.6415C 28.623,33.6415 27.4953,33.8526 26.4052,34.2748C 25.315,34.697 24.3419,35.3342 23.4856,36.1865L 30.2344,42.9174L 25.9027,47.9032L 22.6532,51.8425L 20.5988,54.5836C 20.1212,55.2892 19.8823,55.753 19.8823,55.975L 19.8645,56.0701L 19.9002,56.088L 19.9002,56.1474L 19.9358,56.1058L 20.0131,56.1236C 20.2351,56.1236 20.6989,55.8888 21.4045,55.419L 24.1457,53.3765L 28.0849,50.1151L 33.0945,45.7775L 39.8016,52.5025C 40.6579,51.6462 41.2961,50.6731 41.7163,49.5829C 42.1365,48.4928 42.3466,47.367 42.3466,46.2056C 42.3466,45.4603 42.2603,44.729 42.0879,44.0115C 41.9155,43.294 41.6548,42.6003 41.3069,41.9304L 49.2202,34.0161C 50.0011,34.3372 50.7939,34.4978 51.5986,34.4978C 52.4192,34.4978 53.2189,34.3362 53.9979,34.0132C 54.7768,33.6901 55.4894,33.2015 56.1355,32.5475 Z "/>

                        <ContentPresenter VerticalAlignment="Center" Margin="10,0,0,0" />
                    </StackPanel>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="False">
                            <Setter TargetName="MyPin" Property="Data" Value="F1 M 32.3691,30.2225L 33.2253,29.3901L 15.361,11.5258C 13.9814,12.7067 12.6951,13.9936 11.5148,15.3738L 26.6252,30.4842C 27.743,30.1631 28.8767,30.0025 30.0263,30.0025C 30.8191,30.0025 31.6,30.0759 32.3691,30.2225 Z M 45.5039,49.3629L 60.6292,64.4826C 62.0123,63.2996 63.3017,62.0101 64.4846,60.6268L 46.6218,42.7866L 45.7834,43.619L 45.9439,44.7726L 45.9915,45.9261L 45.8785,47.6713L 45.5039,49.3629 Z M 56.1355,32.5475L 43.4466,19.8526C 42.7886,20.4987 42.298,21.2123 41.9749,21.9932C 41.6519,22.7741 41.4903,23.5729 41.4903,24.3895C 41.4903,25.1942 41.6529,25.987 41.9779,26.7679L 34.0577,34.6821C 33.3918,34.3372 32.6991,34.0776 31.9796,33.9032C 31.2601,33.7288 30.5298,33.6415 29.7885,33.6415C 28.623,33.6415 27.4953,33.8526 26.4052,34.2748C 25.315,34.697 24.3419,35.3342 23.4856,36.1865L 30.2344,42.9174L 25.9027,47.9032L 22.6532,51.8425L 20.5988,54.5836C 20.1212,55.2892 19.8823,55.753 19.8823,55.975L 19.8645,56.0701L 19.9002,56.0879L 19.9002,56.1474L 19.9358,56.1058L 20.0131,56.1236C 20.2351,56.1236 20.6989,55.8888 21.4045,55.419L 24.1457,53.3765L 28.0849,50.1151L 33.0945,45.7775L 39.8016,52.5025C 40.6579,51.6462 41.2961,50.6731 41.7163,49.5829C 42.1365,48.4928 42.3466,47.367 42.3466,46.2056C 42.3466,45.4603 42.2603,44.729 42.0879,44.0115C 41.9155,43.294 41.6548,42.6003 41.306,41.9304L 49.2202,34.0161C 50.0011,34.3372 50.7939,34.4978 51.5986,34.4978C 52.4192,34.4978 53.219,34.3362 53.9979,34.0132C 54.7768,33.6901 55.4894,33.2015 56.1355,32.5475 Z " />                                
                            <Setter TargetName="MyPin" Property="Fill" Value="Gray" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</Style>

Using

<StackPanel Orientation="Vertical" HorizontalAlignment="Center">
    <CheckBox Height="35"
              Style="{StaticResource styleCustomCheckBox}" 
              Content="MySolution1" />

    <CheckBox Height="35"
              Style="{StaticResource styleCustomCheckBox}" 
              Content="MySolution2" />
</StackPanel>

Output

我们也可以将Path's存储在资源中,像这样引用它们:

<Path x:Key="MyPath" Data="F1 M 38,19C 48.4934,19 57,27.5066 ... />

...

<Setter TargetName="MainPath" Property="Data"
        Value="{Binding Source={StaticResource MyPath}, Path=Data}" />

Edit

为了指定任意图标,我创建了两个附加的依赖属性(字符串类型):

  • IsCheckedOnData

  • IsCheckedOffData

IsCheckedOnData 包含由IsChecked = "True" 提供的Data 值,IsCheckedOffDataIsChecked = "False" 提供的值。

现在您只需要确定图标字符串并定义这样的资源(例如)。

完整示例:

XAML

<Window x:Class="CustomCheckBoxHelp.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:CustomCheckBoxHelp"
    xmlns:sys="clr-namespace:System;assembly=mscorlib"
    WindowStartupLocation="CenterScreen"
    Title="MainWindow" Height="350" Width="525">

<Window.Resources>
    <sys:String x:Key="Up">
        F1 M 37.8516,35.625L 34.6849,38.7917L 23.6016,50.2708L 
        23.6016,39.9792L 37.8516,24.9375L 52.1016,39.9792L 52.1016,
        50.2708L 41.0182,38.7917L 37.8516,35.625 Z
    </sys:String>

    <sys:String x:Key="Down">
        F1 M 37.8516,39.5833L 52.1016,24.9375L 52.1016,35.2292L 
        37.8516,50.2708L 23.6016,35.2292L 23.6016,24.9375L 37.8516,39.5833 Z
    </sys:String>

    <Style x:Key="styleCustomCheckBox" TargetType="{x:Type CheckBox}">
        <Setter Property="FontFamily" Value="Verdana" />
        <Setter Property="FontSize" Value="14" />

        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type CheckBox}">
                    <StackPanel Orientation="Horizontal">
                        <Path x:Name="MyPin" Width="18" Height="18" Stretch="Fill" Fill="#FF000000" 
                              Data="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:CustomCheckBoxClass.IsCheckedOnData)}" />
                        <ContentPresenter VerticalAlignment="Center" Margin="10,0,0,0" />
                    </StackPanel>

                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="False">
                            <Setter TargetName="MyPin" Property="Data"
                                    Value="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(local:CustomCheckBoxClass.IsCheckedOffData)}" />
                            <Setter TargetName="MyPin" Property="Fill" Value="Gray" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</Window.Resources>

<Grid>
    <StackPanel Orientation="Vertical" HorizontalAlignment="Center" Background="Beige">
        <CheckBox Height="35" 
                  local:CustomCheckBoxClass.IsCheckedOnData="{StaticResource Up}"
                  local:CustomCheckBoxClass.IsCheckedOffData="{StaticResource Down}"
                  Style="{StaticResource styleCustomCheckBox}" 
                  Content="MySolution1" />

        <CheckBox Height="35" 
                  local:CustomCheckBoxClass.IsCheckedOnData="{StaticResource Up}"
                  local:CustomCheckBoxClass.IsCheckedOffData="{StaticResource Down}"
                  Style="{StaticResource styleCustomCheckBox}" 
                  Content="MySolution2" />
    </StackPanel>
</Grid>
</Window>

Code behind

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();            
    }
}

public class CustomCheckBoxClass : DependencyObject
{
    #region IsCheckedOnDataProperty

    public static readonly DependencyProperty IsCheckedOnDataProperty;

    public static void SetIsCheckedOnData(DependencyObject DepObject, string value)
    {
        DepObject.SetValue(IsCheckedOnDataProperty, value);
    }

    public static string GetIsCheckedOnData(DependencyObject DepObject)
    {
        return (string)DepObject.GetValue(IsCheckedOnDataProperty);
    }

    #endregion

    #region IsCheckedOffDataProperty

    public static readonly DependencyProperty IsCheckedOffDataProperty;

    public static void SetIsCheckedOffData(DependencyObject DepObject, string value)
    {
        DepObject.SetValue(IsCheckedOffDataProperty, value);
    }

    public static string GetIsCheckedOffData(DependencyObject DepObject)
    {
        return (string)DepObject.GetValue(IsCheckedOffDataProperty);
    }

    #endregion

    static CustomCheckBoxClass()
    {
        PropertyMetadata MyPropertyMetadata = new PropertyMetadata(string.Empty);

        IsCheckedOnDataProperty = DependencyProperty.RegisterAttached("IsCheckedOnData",
                                                            typeof(string),
                                                            typeof(CustomCheckBoxClass),
                                                            MyPropertyMetadata);

        IsCheckedOffDataProperty = DependencyProperty.RegisterAttached("IsCheckedOffData",
                                                            typeof(string),
                                                            typeof(CustomCheckBoxClass),
                                                            MyPropertyMetadata);
    }        
}

Note: 在样式中我没有使用过TemplateBinding,因为TemplateBinding 在模板之外或其VisualTree 属性之外不起作用,所以你甚至不能在模板的触发器中使用TemplateBinding。因此,我们必须使用构造 {RelativeSource TemplatedParent}Path 等于要检索其值的依赖属性。

【讨论】:

  • 非常感谢您的回复。对图像数据使用如此广泛的字符串似乎很奇怪。如果这真的是标准方式,那就这样吧。我在表达式设计中设计了我自己的所有图标,所以我将研究一个转换实用程序......但我想知道如何更改自定义复选框的实际图像 - 所以说我是否想显示刻度线和十字线相反,如何在不创建另一种样式的情况下做到这一点 - 或者这是不可能的?
  • @Killercam,最好的做法是将此矢量图像数据保存在单独的资源文件中,而不是本地资源中。
  • @AnatoliyNikolaev 我想从资源文件中引用更复杂的矢量图形。你能看看这个新问题stackoverflow.com/questions/18541408/…
  • @Killercam:是的,现在看。
【解决方案2】:

抱歉,我还不知道如何在这些资源中引用图像,但是如果您可以将图像添加到应用程序根目录中名为 Images 的文件夹中,那么您将能够简单地引用图像像这样:

<Image Source="/ApplicationName;component/Images/SomeImage16.png" />

【讨论】:

    【解决方案3】:

    正如您所提到的,您可以通过选中和取消选中来更改复选框触发器。并且图像会显示相应的触发器。您的 xml 代码对我有好处。我只是删除了触发器 true 部分。因为默认情况下 false 部分处于焦点,并且单击复选框图像 UnPinned16.png 后可见。并且再次点击图片 Pinned16.png 是可见的。

    <Style x:Key="styleCustomCheckBox" 
           TargetType="{x:Type CheckBox}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type CheckBox}">
                    <StackPanel Orientation="Horizontal">
                        <Image x:Name="imageCheckBox" 
                               Width="16" 
                               Height="16" Source="F:\Camus\ResourceStudio\Graphics\Images\UnPinned16.png"/>
                        <ContentPresenter VerticalAlignment="Center"/>
                    </StackPanel>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsChecked" Value="False">
                            <Setter TargetName="imageCheckBox" 
                                    Property="Source" 
                                    Value="F:\Camus\ResourceStudio\Graphics\Images\Pinned16.png"/>
                        </Trigger>                        
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    我在文本块下使用此复选框

    <CheckBox Style="{StaticResource styleCustomCheckBox}" 
                      HorizontalAlignment="Left" 
                      VerticalAlignment="Center"
                      Margin="4,0,4,0"/>
    

    【讨论】:

      猜你喜欢
      • 2012-05-03
      • 1970-01-01
      • 2011-04-27
      • 1970-01-01
      • 2011-02-24
      • 1970-01-01
      • 1970-01-01
      • 2011-06-15
      • 2011-02-07
      相关资源
      最近更新 更多