WPF: кнопка ControlTemplate + пробел = исключение?

Я собрал шаблон в Expression Blend для кнопки, и он работает нормально, пока я не перейду к нему и не нажму пробел. Я получаю следующую ошибку:

Свойство InvalidOperationException '[Unknown]' не указывает на DependencyObject в пути '(0).(1).[0].(2)'.

Код выглядит следующим образом:

    <ControlTemplate x:Key="EmailButton" TargetType="{x:Type Button}">
        <ControlTemplate.Resources>
            <Storyboard x:Key="MouseOverStoryboard">
                <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="border" Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <SplineColorKeyFrame KeyTime="00:00:00.4000000" Value="#FF55679E"/>
                </ColorAnimationUsingKeyFrames>
            </Storyboard>
            <Storyboard x:Key="UnMouseOverStoryboard">
                <ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="border" Storyboard.TargetProperty="(Panel.Background).(GradientBrush.GradientStops)[0].(GradientStop.Color)">
                    <SplineColorKeyFrame KeyTime="00:00:00.4000000" Value="#FF92A2D3"/>
                </ColorAnimationUsingKeyFrames>
            </Storyboard>
        </ControlTemplate.Resources>
        <Border x:Name="border" BorderBrush="#FF000000" BorderThickness="2,2,2,2" CornerRadius="4,4,4,4">
            <Border.Background>
                <LinearGradientBrush EndPoint="0.47,-0.01" StartPoint="0.47,0.808">
                    <GradientStop Color="#FF92A2D3" Offset="0"/>
                    <GradientStop Color="#FFFFFFFF" Offset="1"/>
                </LinearGradientBrush>
            </Border.Background>
            <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" Margin="{TemplateBinding Padding}"/>
        </Border>
        <ControlTemplate.Triggers>
            <Trigger Property="IsPressed" Value="True">
                <Setter Property="Background" TargetName="border" Value="#FF92A2D3"/>
            </Trigger>
            <Trigger Property="IsMouseOver" Value="True">
                <Trigger.EnterActions>
                    <BeginStoryboard x:Name="MouseOverStoryboard_BeginStoryboard" Storyboard="{StaticResource MouseOverStoryboard}"/>
                </Trigger.EnterActions>
                <Trigger.ExitActions>
                    <BeginStoryboard x:Name="UnMouseOverStoryboard_BeginStoryboard" Storyboard="{StaticResource UnMouseOverStoryboard}"/>
                </Trigger.ExitActions>
            </Trigger>
        </ControlTemplate.Triggers>
    </ControlTemplate>

Может показаться, что запускается либо MouseOverStoryboard, либо UnMouseOverStoryboard (путь, указанный в ошибке, похоже, соответствует TargetProperty). Я не уверен, почему любой из них срабатывает при нажатии клавиши пробела... Есть предложения?

РЕДАКТИРОВАТЬ: благодаря Райану Версоу я попробовал следующее, что теперь не позволяет щелчку пробела вызывать исключение:

            <Trigger Property="IsPressed" Value="True">
                <Setter Property="Background" TargetName="border">
                    <Setter.Value>
                        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                            <GradientStop Color="#FF92A2D3" Offset="0"/>
                            <GradientStop Color="#FF92A2D3" Offset="1"/>
                        </LinearGradientBrush>
                    </Setter.Value>
                </Setter>
            </Trigger>

Теперь тип кисти остается постоянным (LinearGradientBrush), и всегда доступен 0-й GradientStop.

Мне все еще интересно узнать еще об одном: как лучше это сделать, учитывая, что это похоже на хак (например, добавляется/анимируется третья остановка градиента, затем третья GradientStop необходимо добавить, когда IsPressed==True).

Спасибо за предложения! Надеюсь, это поможет и кому-то еще.


person Charles    schedule 19.05.2009    source источник


Ответы (3)


Я не уверен, какое оптимальное решение было бы, но я нашел то, что работает.

Создайте LinearGradientBrush в своих ресурсах:

<LinearGradientBrush x:Key="solidBrush">
    <GradientStop Color="#FF92A2D3"/>
</LinearGradientBrush>

Измените триггер IsPressed на следующий (изменяется только Value):

<Trigger Property="IsPressed" Value="True">
    <Setter Property="Background" TargetName="border" Value="{StaticResource solidBrush}"/>
</Trigger>

Это должно заменить весь ваш фон на новый (который также является LinearGradientBrush).

person Ryan Versaw    schedule 19.05.2009
comment
Чтобы отдать должное, я попытался заменить фон аналогичной кистью из-за ответа Пвиннштейна. Другие способы могут работать, но это сработало для меня. - person Ryan Versaw; 19.05.2009

Если вы нажмете пробел, это будет похоже на нажатие кнопки.
Вы должны посмотреть на триггер IsPressed

person Eduardo Molteni    schedule 19.05.2009

Похоже, что сеттер вашего триггера IsPressed пытается присвоить значение цвета (# FF92A2D3) свойству Background вашей границы. Однако свойство фона вашей границы содержит кисть линейного градиента, а не кисть сплошного цвета. Впрочем, это всего лишь мнение на первый взгляд.

person Mark Carpenter    schedule 19.05.2009