【问题标题】:WP8.1 How can i bind property in the visual state manager of a toggle button styleWP8.1 如何在切换按钮样式的可视状态管理器中绑定属性
【发布时间】:2016-03-25 09:40:47
【问题描述】:

我决定使用自定义样式自定义切换按钮:它包含图像和文本。 我的按钮的正常状态使用特定的图像和特定的文本前景。 选中状态使用其他状态。

但是...该开关不适用于我的图像。

我创建了一个自定义切换按钮。代码就在这里:

class CustomToggleButton : ToggleButton
{

    public String ImageSource
    {
        get { return (String)GetValue(ImageSourceProperty); }
        set { SetValue(ImageSourceProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ImageSource.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ImageSourceProperty =
        DependencyProperty.Register("ImageSource", typeof(String), typeof(CustomToggleButton), new PropertyMetadata(String.Empty));



    public String SelectedImageSource
    {
        get { return (String)GetValue(SelectedImageSourceProperty); }
        set { SetValue(SelectedImageSourceProperty, value); }
    }

    // Using a DependencyProperty as the backing store for SelectedImageSource.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty SelectedImageSourceProperty =
        DependencyProperty.Register("SelectedImageSource", typeof(String), typeof(CustomToggleButton), new PropertyMetadata(String.Empty));


}

我这样使用我的控件:

<controls:CustomToggleButton ImageSource="/Resources/home.png" SelectedImageSource="/Resources/home-neg.png" FontSize="18"
                             Content="Acceuil" Style="{StaticResource HamburgerMenuItemStyle}"   VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>

这里是自定义切换按钮样式:

<x:Double x:Key="TextStyleLargeFontSize">18.14</x:Double>
    <Thickness x:Key="PhoneButtonContentPadding">9.5,0,9.5,3.5</Thickness>
    <x:Double x:Key="PhoneButtonMinHeight">57.5</x:Double>
    <x:Double x:Key="PhoneButtonMinWidth">109</x:Double>
    <Style x:Key="HamburgerMenuItemStyle" TargetType="ToggleButton">
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="BorderBrush" Value="{ThemeResource PhoneForegroundBrush}"/>
        <Setter Property="Foreground" Value="{ThemeResource PhoneForegroundBrush}"/>
        <Setter Property="BorderThickness" Value="0"/>
        <Setter Property="FontFamily" Value="{StaticResource StandardFont}"/>
        <Setter Property="FontSize" Value="{ThemeResource TextStyleLargeFontSize}"/>
        <Setter Property="Padding" Value="{ThemeResource PhoneButtonContentPadding}"/>
        <Setter Property="MinHeight" Value="{ThemeResource PhoneButtonMinHeight}"/>
        <Setter Property="MinWidth" Value="{ThemeResource PhoneButtonMinWidth}"/>
        <Setter Property="HorizontalAlignment" Value="Left"/>
        <Setter Property="VerticalAlignment" Value="Center"/>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="controls:CustomToggleButton">
                    <Grid Background="Transparent">
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="CommonStates">
                                <VisualState x:Name="Normal">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="EnabledBackground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="EnabledContent">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource IaF-SColor-DarkGreen}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Source" Storyboard.TargetName="ToggleImage">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding ImageSource}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="PointerOver"/>
                                <VisualState x:Name="Pressed"/>
                                <VisualState x:Name="Disabled"/>
                                <VisualState x:Name="Checked">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="EnabledBackground">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource IaF-SColor-DarkGreen}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="EnabledContent">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
                                        </ObjectAnimationUsingKeyFrames>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Source" Storyboard.TargetName="ToggleImage">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding SelectedImageSource}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="CheckedPointerOver"/>
                                <VisualState x:Name="CheckedPressed"/>
                                <VisualState x:Name="CheckedDisabled"/>
                                <VisualState x:Name="Indeterminate"/>
                                <VisualState x:Name="IndeterminatePointerOver"/>
                                <VisualState x:Name="IndeterminatePressed"/>
                                <VisualState x:Name="IndeterminateDisabled"/>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <Border x:Name="EnabledBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Margin="{ThemeResource PhoneTouchTargetOverhang}">
                            <ContentPresenter AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding ContentTemplate}" 
                                              Foreground="{TemplateBinding Foreground}" Margin="{TemplateBinding Padding}" >
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition/>
                                        <ColumnDefinition/>
                                        <ColumnDefinition/>
                                        <ColumnDefinition/>
                                    </Grid.ColumnDefinitions>
                                    <Image x:Name="ToggleImage" Source="{Binding ImageSource}"/>
                                    <TextBlock Grid.Column="1" Grid.ColumnSpan="3" x:Name="EnabledContent" Style="{StaticResource BaseTextBlockStyle}" Foreground="{TemplateBinding Foreground}"
                                               FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" Text="{TemplateBinding Content}" Margin="10,0,0,0"
                                               TextAlignment="Left" VerticalAlignment="Center"/>
                                </Grid>
                            </ContentPresenter>
                        </Border>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

如您所见,我尝试为两种不同的状态设置自定义切换按钮属性:

正常状态:

<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Source" Storyboard.TargetName="ToggleImage">
    <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding ImageSource}"/>
</ObjectAnimationUsingKeyFrames>

检查状态:

<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Source" Storyboard.TargetName="ToggleImage">
    <DiscreteObjectKeyFrame KeyTime="0" Value="{Binding SelectedImageSource}"/>
</ObjectAnimationUsingKeyFrames>

而且……它根本不起作用。

编辑:

对于有兴趣的伙伴,我的解决方案如下。

【问题讨论】:

  • 您尝试过 TemplateBinding 吗?
  • 试试这个 {Binding RelativeSource={RelativeSource TemplateParent},Path=ImageSource}
  • 第一个解决方案不起作用,第二个解决方案让我的应用崩溃!
  • 你能告诉我例外情况吗?
  • 它在“App.gics”中崩溃并显示以下消息:test.exe!test.App.InitializeComponent.AnonymousMethod__2(object sender, Windows.UI.Xaml.UnhandledExceptionEventArgs e) 我认为 C# 第 50 行XAML 不喜欢我们尝试绑定数据的方式。

标签: c# xaml visual-studio-2013 windows-phone-8.1


【解决方案1】:

根据link,这是不可能的。 您不能使用动态资源 引用或数据绑定表达式来设置 Storyboard 或动画属性值。这是因为 ControlTemplate 中的所有内容都必须是线程安全的,并且计时系统必须冻结 Storyboard 对象以使其成为线程安全的。如果 Storyboard 或其子时间线包含动态资源引用或数据绑定表达式,则无法冻结 Storyboard

【讨论】:

    【解决方案2】:

    最好有重叠的图像,并根据切换按钮的状态更改图像的可见性

    【讨论】:

    • 确实,这可能是一个解决方案。但是,我想知道是否可以在可视状态管理器中实现这一点。
    【解决方案3】:

    最后,我的解决方案与最初的想法有点不同:我集成了一个附加图像来管理“选定状态”。然后,我在视觉状态管理器中使用图像可见性属性。

    我在自定义切换按钮类上有一个附加属性来设置“选定的图像源”

    public class CustomToggleButton : ToggleButton
    {
    
        [...]
    
        public String SelectedImageSource
        {
            get { return (String)GetValue(SelectedImageSourceProperty); }
            set { SetValue(SelectedImageSourceProperty, value); }
        }
    
        // Using a DependencyProperty as the backing store for SelectedImageSource.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedImageSourceProperty =
            DependencyProperty.Register("SelectedImageSource", typeof(String), typeof(CustomToggleButton), new PropertyMetadata(String.Empty));
    
    
    }
    

    然后我修改了对这个自定义控件的调用:

    <controls:CustomToggleButton ImageSource="/Resources/home.png" SelectedImageSource="/Resources/home-neg.png" FontSize="18" Click="CustomToggleButton_Click"
                                 Content="Acceuil" Style="{StaticResource HamburgerMenuItemStyle}"   
                                 VerticalAlignment="Stretch" HorizontalAlignment="Stretch"/>
    

    最后,我通过设置另一个图像“SelectedItemImage”修改了自定义切换按钮样式,并且我使用了可见性属性来隐藏或显示正确的图像。

    <Style x:Key="HamburgerMenuItemStyle" TargetType="ToggleButton">
            <Setter Property="Background" Value="Transparent"/>
            <Setter Property="BorderThickness" Value="0"/>
            <Setter Property="FontFamily" Value="{StaticResource StandardFont}"/>
            <Setter Property="HorizontalAlignment" Value="Left"/>
            <Setter Property="VerticalAlignment" Value="Center"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="controls:CustomToggleButton" >
                        <Grid Background="Transparent">
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CommonStates">
                                    <VisualState x:Name="Normal">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ItemBorder">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ItemTextBlock">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource IaF-SColor-DarkGreen}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ItemImage">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="SelectedItemImage">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="PointerOver"/>
                                    <VisualState x:Name="Pressed"/>
                                    <VisualState x:Name="Disabled"/>
                                    <VisualState x:Name="Checked">
                                        <Storyboard>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ItemBorder">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource IaF-SColor-DarkGreen}"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ItemTextBlock">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="White"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ItemImage">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                                            </ObjectAnimationUsingKeyFrames>
                                            <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="SelectedItemImage">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                                            </ObjectAnimationUsingKeyFrames>
                                        </Storyboard>
                                    </VisualState>
                                    <VisualState x:Name="CheckedPointerOver"/>
                                    <VisualState x:Name="CheckedPressed"/>
                                    <VisualState x:Name="CheckedDisabled"/>
                                    <VisualState x:Name="Indeterminate"/>
                                    <VisualState x:Name="IndeterminatePointerOver"/>
                                    <VisualState x:Name="IndeterminatePressed"/>
                                    <VisualState x:Name="IndeterminateDisabled"/>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Border x:Name="ItemBorder" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                                <ContentPresenter AutomationProperties.AccessibilityView="Raw" ContentTemplate="{TemplateBinding ContentTemplate}" 
                                                  Margin="{TemplateBinding Padding}" VerticalAlignment="Center">
                                    <Grid>
                                        <Grid.ColumnDefinitions>
                                            <ColumnDefinition Width="*"/>
                                            <ColumnDefinition Width="5*"/>
                                        </Grid.ColumnDefinitions>
                                        <Image x:Name="ItemImage" Source="{Binding Path=ImageSource, RelativeSource={RelativeSource TemplatedParent}}" 
                                               VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MaxHeight="{StaticResource MenuButtonImageSize}" MaxWidth="{StaticResource MenuButtonImageSize}"/>
                                        <Image x:Name="SelectedItemImage" Source="{Binding Path=SelectedImageSource, RelativeSource={RelativeSource TemplatedParent}}" 
                                               VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MaxHeight="{StaticResource MenuButtonImageSize}" MaxWidth="{StaticResource MenuButtonImageSize}"/>
                                        <TextBlock Grid.Column="1" x:Name="ItemTextBlock" Style="{StaticResource BaseTextBlockStyle}" Foreground="{TemplateBinding Foreground}"
                                                   FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" Text="{TemplateBinding Content}" Margin="20,0,0,0"
                                                   TextAlignment="Left" VerticalAlignment="Center"/>
                                    </Grid>
                                </ContentPresenter>
                            </Border>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>
    

    主要变化就在这里:

    <Image x:Name="ItemImage" Source="{Binding Path=ImageSource, RelativeSource={RelativeSource TemplatedParent}}" 
                                               VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MaxHeight="{StaticResource MenuButtonImageSize}" MaxWidth="{StaticResource MenuButtonImageSize}"/>
    <Image x:Name="SelectedItemImage" Source="{Binding Path=SelectedImageSource, RelativeSource={RelativeSource TemplatedParent}}" 
                                               VerticalAlignment="Stretch" HorizontalAlignment="Stretch" MaxHeight="{StaticResource MenuButtonImageSize}" MaxWidth="{StaticResource MenuButtonImageSize}"/>
    

    我们将源绑定到自定义类依赖属性(感谢 Archana 的建议),然后我们在可视状态管理器中使用可见性,如下所示:

    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="ItemImage">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
    </ObjectAnimationUsingKeyFrames>
    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="(UIElement.Visibility)" Storyboard.TargetName="SelectedItemImage">
                                                <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
    </ObjectAnimationUsingKeyFrames>
    

    【讨论】:

    • 图片是静态的吗?如果是,则有一种简单的方法可以使图像具有控件的样式,并在控件的视觉状态中切换图像的可见性。否则,依赖属性就是方法。
    • “静态图像”是什么意思?我有一个图像文件夹,并且我多次使用不同的图像集使用我的切换按钮。
    • 例如,切换按钮用于布尔用例,如 yes-no true-false。所以我的意思是静态图像,就像一个刻度交叉图像切换。其中一个值相同。勾选图像表示是,交叉图像表示否。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    相关资源
    最近更新 更多