UWP 自定义复选框 - ToggleIcon
UWP Customized Checkbox - ToggleIcon
我正在尝试创建本质上是 Checkbox 控件的自定义版本,但无法使其按我希望的方式工作。这个想法(我称之为 ToggleIcon)本质上是一个图标,当它被点击时会以某种方式发生变化以表示它已被 selected。例如,基本想法是当控件处于未选中状态时显示一个灰色图标,当用户单击该图标时,它将切换到选中状态,由相同的图标显示,但颜色为绿色。
我遵循了 this MSDN 指南,该指南也涉及自定义复选框,但差异导致它无法正常工作。我在控件中添加了两个 DependencyProperties,名为 CheckedImage
和 UncheckedImage
,类型均为 ImageSource
。这个想法是让用户在 XAML 中添加控件,并为每个控件提供指向 select 所需图标的路径。我也有这些由灰色和绿色复选标记图标组成的默认值。但是,当我对此进行测试时,我不断收到 UriFormatException 提示无法确定格式。
有人可以查看这段代码,看看是否能找到问题所在吗?或者,也将不胜感激关于此类任务的任何指南的链接,我什至不知道如何 google 找到有用的结果。
切换图标代码:
public sealed partial class ToggleIcon : UserControl
{
public ImageSource UncheckedImage
{
get { return (ImageSource)GetValue(UncheckedImageProperty); }
set { SetValue(UncheckedImageProperty, value); }
}
public static readonly DependencyProperty UncheckedImageProperty =
DependencyProperty.Register("UncheckedImage", typeof(ImageSource), typeof(ToggleIcon), new PropertyMetadata(new System.Uri("Assets/default-unchecked.png")));
public ImageSource CheckedImage
{
get { return (ImageSource)GetValue(CheckedImageProperty); }
set { SetValue(CheckedImageProperty, value); }
}
public static readonly DependencyProperty CheckedImageProperty =
DependencyProperty.Register("CheckedImage", typeof(ImageSource), typeof(ToggleIcon), new PropertyMetadata(new System.Uri("Assets/default-checked.png")));
public ToggleIcon()
{
this.InitializeComponent();
DataContext = this;
}
}
ToggleIcon XAML:
<UserControl
x:Class="CustomControlScratchpad.ToggleIcon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CustomControlScratchpad"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="128"
d:DesignWidth="128">
<UserControl.Resources>
<ControlTemplate x:Key="ToggleIconTemplate" TargetType="CheckBox">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="UriSource" Storyboard.TargetName="CheckedState" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="UriSource" Storyboard.TargetName="UncheckedState" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<BitmapIcon x:Name="UncheckedState" UriSource="{Binding UncheckedImage }" />
<BitmapIcon x:Name="CheckedState" UriSource="{Binding CheckedImage}" />
</Grid>
</Border>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<CheckBox Template="{StaticResource ToggleIconTemplate}" />
</Grid>
</UserControl>
至于 MainPage.xaml,我添加的唯一代码是插入 ToggleIcon 控件,即-<local:ToggleIcon />
。 MainPage.xaml.cs 没有对 VisualStudio 初始模板进行任何更改。
问题是你做的动画做错了属性。 TargetProperty
应该是 BitmapIcon 的 Opacity,为了正确显示状态,我们需要将 bitmapicon 的默认 Opacity 设置为 0,并通过 VisualState
.
切换到不同的状态
并且默认的 UncheckedImage 和 CheckedImage 值应该包含 ms-appx uri shcheme。请参考以下完整代码。
public sealed partial class ToggleIcon : UserControl
{
public ImageSource UncheckedImage
{
get { return (ImageSource)GetValue(UncheckedImageProperty); }
set { SetValue(UncheckedImageProperty, value); }
}
public static readonly DependencyProperty UncheckedImageProperty =
DependencyProperty.Register("UncheckedImage", typeof(ImageSource), typeof(ToggleIcon), new PropertyMetadata(new System.Uri("ms-appx:///Assets/default-unchecked.png")));
public ImageSource CheckedImage
{
get { return (ImageSource)GetValue(CheckedImageProperty); }
set { SetValue(CheckedImageProperty, value); }
}
public static readonly DependencyProperty CheckedImageProperty =
DependencyProperty.Register("CheckedImage", typeof(ImageSource), typeof(ToggleIcon), new PropertyMetadata(new System.Uri("ms-appx:///Assets/default-checked.png")));
public ToggleIcon()
{
this.InitializeComponent();
DataContext = this;
}
}
Xaml代码
<UserControl.Resources>
<ControlTemplate x:Key="ToggleIconTemplate" TargetType="CheckBox">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<BitmapIcon
x:Name="UncheckedState"
Opacity="0"
UriSource="{Binding UncheckedImage}" />
<BitmapIcon
x:Name="CheckedState"
Opacity="0"
UriSource="{Binding CheckedImage}" />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="CheckedState"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="UncheckedState"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<CheckBox
Width="32"
Height="32"
Template="{StaticResource ToggleIconTemplate}" />
</Grid>
我正在尝试创建本质上是 Checkbox 控件的自定义版本,但无法使其按我希望的方式工作。这个想法(我称之为 ToggleIcon)本质上是一个图标,当它被点击时会以某种方式发生变化以表示它已被 selected。例如,基本想法是当控件处于未选中状态时显示一个灰色图标,当用户单击该图标时,它将切换到选中状态,由相同的图标显示,但颜色为绿色。
我遵循了 this MSDN 指南,该指南也涉及自定义复选框,但差异导致它无法正常工作。我在控件中添加了两个 DependencyProperties,名为 CheckedImage
和 UncheckedImage
,类型均为 ImageSource
。这个想法是让用户在 XAML 中添加控件,并为每个控件提供指向 select 所需图标的路径。我也有这些由灰色和绿色复选标记图标组成的默认值。但是,当我对此进行测试时,我不断收到 UriFormatException 提示无法确定格式。
有人可以查看这段代码,看看是否能找到问题所在吗?或者,也将不胜感激关于此类任务的任何指南的链接,我什至不知道如何 google 找到有用的结果。
切换图标代码:
public sealed partial class ToggleIcon : UserControl
{
public ImageSource UncheckedImage
{
get { return (ImageSource)GetValue(UncheckedImageProperty); }
set { SetValue(UncheckedImageProperty, value); }
}
public static readonly DependencyProperty UncheckedImageProperty =
DependencyProperty.Register("UncheckedImage", typeof(ImageSource), typeof(ToggleIcon), new PropertyMetadata(new System.Uri("Assets/default-unchecked.png")));
public ImageSource CheckedImage
{
get { return (ImageSource)GetValue(CheckedImageProperty); }
set { SetValue(CheckedImageProperty, value); }
}
public static readonly DependencyProperty CheckedImageProperty =
DependencyProperty.Register("CheckedImage", typeof(ImageSource), typeof(ToggleIcon), new PropertyMetadata(new System.Uri("Assets/default-checked.png")));
public ToggleIcon()
{
this.InitializeComponent();
DataContext = this;
}
}
ToggleIcon XAML:
<UserControl
x:Class="CustomControlScratchpad.ToggleIcon"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:CustomControlScratchpad"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="128"
d:DesignWidth="128">
<UserControl.Resources>
<ControlTemplate x:Key="ToggleIconTemplate" TargetType="CheckBox">
<Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="UriSource" Storyboard.TargetName="CheckedState" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<DoubleAnimation Duration="0" To="1" Storyboard.TargetProperty="UriSource" Storyboard.TargetName="UncheckedState" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<BitmapIcon x:Name="UncheckedState" UriSource="{Binding UncheckedImage }" />
<BitmapIcon x:Name="CheckedState" UriSource="{Binding CheckedImage}" />
</Grid>
</Border>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<CheckBox Template="{StaticResource ToggleIconTemplate}" />
</Grid>
</UserControl>
至于 MainPage.xaml,我添加的唯一代码是插入 ToggleIcon 控件,即-<local:ToggleIcon />
。 MainPage.xaml.cs 没有对 VisualStudio 初始模板进行任何更改。
问题是你做的动画做错了属性。 TargetProperty
应该是 BitmapIcon 的 Opacity,为了正确显示状态,我们需要将 bitmapicon 的默认 Opacity 设置为 0,并通过 VisualState
.
并且默认的 UncheckedImage 和 CheckedImage 值应该包含 ms-appx uri shcheme。请参考以下完整代码。
public sealed partial class ToggleIcon : UserControl
{
public ImageSource UncheckedImage
{
get { return (ImageSource)GetValue(UncheckedImageProperty); }
set { SetValue(UncheckedImageProperty, value); }
}
public static readonly DependencyProperty UncheckedImageProperty =
DependencyProperty.Register("UncheckedImage", typeof(ImageSource), typeof(ToggleIcon), new PropertyMetadata(new System.Uri("ms-appx:///Assets/default-unchecked.png")));
public ImageSource CheckedImage
{
get { return (ImageSource)GetValue(CheckedImageProperty); }
set { SetValue(CheckedImageProperty, value); }
}
public static readonly DependencyProperty CheckedImageProperty =
DependencyProperty.Register("CheckedImage", typeof(ImageSource), typeof(ToggleIcon), new PropertyMetadata(new System.Uri("ms-appx:///Assets/default-checked.png")));
public ToggleIcon()
{
this.InitializeComponent();
DataContext = this;
}
}
Xaml代码
<UserControl.Resources>
<ControlTemplate x:Key="ToggleIconTemplate" TargetType="CheckBox">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<BitmapIcon
x:Name="UncheckedState"
Opacity="0"
UriSource="{Binding UncheckedImage}" />
<BitmapIcon
x:Name="CheckedState"
Opacity="0"
UriSource="{Binding CheckedImage}" />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="CheckedState"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unchecked">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="UncheckedState"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Border>
</ControlTemplate>
</UserControl.Resources>
<Grid>
<CheckBox
Width="32"
Height="32"
Template="{StaticResource ToggleIconTemplate}" />
</Grid>