在数据触发器中使用依赖项属性

时间:2015-02-20 11:03:29

标签: c# wpf xaml dependency-properties datatrigger

我有以下自定义控件:

public class AnimatedButton : Button
    {
        public enum ButtonStates
        {
            None,
            Busy
        }

        public ButtonStates State
        {
            get { return (ButtonStates)GetValue(StateProperty); }
            set { SetValue(StateProperty, value); }
        }

        // Using a DependencyProperty as the backing store for State.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty StateProperty =
            DependencyProperty.Register("State", typeof(ButtonStates), typeof(AnimatedButton), new PropertyMetadata(ButtonStates.None));

        public ImageSource ImageDefault
        {
            get { return (ImageSource)GetValue(ImageDefaultProperty); }
            set { SetValue(ImageDefaultProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ImageDefault.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ImageDefaultProperty =
            DependencyProperty.Register("ImageDefault", typeof(ImageSource), typeof(AnimatedButton), new PropertyMetadata(null));

        public ImageSource ImageBusy
        {
            get { return (ImageSource)GetValue(ImageBusyProperty); }
            set { SetValue(ImageBusyProperty, value); }
        }

        ...
    }

我的目标是根据当前按钮状态显示适当的图像源。例如,如果ButtonState为,则显示默认图像,否则显示忙碌图像,非常简单。这是风格:

<Style TargetType="{x:Type controls:AnimatedButton}">
    ...
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:AnimatedButton}">
                <Border>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>

                        <Image x:Name="img"/>

                        <TextBlock Text="{TemplateBinding Content}"
                                   Grid.Column="1"/>
                    </Grid>
                </Border>

                <ControlTemplate.Triggers>
                    <DataTrigger Binding="{Binding State}" Value="None">
                        <Setter TargetName="img" Property="Source" Value="{Binding ImageDefault}"/>
                    </DataTrigger>
                    <DataTrigger Binding="{Binding State}" Value="Busy">
                        <Setter TargetName="img" Property="Source" Value="{Binding ImageBusy}"/>
                    </DataTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

问题出在 DataTrigger 中,它没有获取依赖项属性状态。将控件添加到视图后,我在输出中收到以下错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'State' property not found on 'object' ''WorkspaceViewModel' (HashCode=56037929)'. BindingExpression:Path=State; DataItem='WorkspaceViewModel' (HashCode=56037929); target element is 'AnimatedButton' (Name=''); target property is 'NoTarget' (type 'Object')

阅读该错误消息,好像它正在 WorkspaceViewModel 上寻找 State 属性,而不是依赖属性所属的控件。这是为什么?

1 个答案:

答案 0 :(得分:1)

DataTriggers中的绑定(正确地)期望State属性位于控件的DataContext中。但是你想要触发控件本身属性的值。

因此,您应该使用触发器而不是DataTriggers:

<ControlTemplate.Triggers>
    <Trigger Property="State" Value="None">
        <Setter TargetName="img" Property="Source"
            Value="{Binding ImageDefault, RelativeSource={RelativeSource TemplatedParent}}"/>
    </Trigger>
    <Trigger Property="State" Value="Busy">
        <Setter TargetName="img" Property="Source"
            Value="{Binding ImageBusy, RelativeSource={RelativeSource TemplatedParent}}"/>
    </Trigger>
</ControlTemplate.Triggers>