2013-08-24 5 views
4

Есть ли все равно, чтобы анимировать TextBox.ForegroundProperty?Анимация TextBox.Foreground в WPF

<Color x:Key="NormalColor">#FF666666</Color> 
<SolidColorBrush x:Key="NormalBrush" Color="{StaticResource NormalColor}" /> 

<Color x:Key="MouseOverColor">#FF666666</Color> 
<SolidColorBrush x:Key="MouseOverBrush" Color="{StaticResource MouseOverColor}" /> 

<ControlTemplate x:Key="RegularTextBoxTemplate" TargetType="{x:Type TextBox}"> 
    <Grid> 
     <VisualStateManager.VisualStateGroups> 
      <VisualStateGroup x:Name="CommonStates"> 
       <VisualStateGroup.Transitions> 
        <VisualTransition GeneratedDuration="0:0:0.1"/> 
       </VisualStateGroup.Transitions> 
       <VisualState x:Name="Normal"/> 
       <VisualState x:Name="MouseOver"> 
        <Storyboard> 
         <!-- storyboard to animating foreground here... --> 
        </Storyboard> 
       </VisualState> 
      </VisualStateGroup > 
     </VisualStateManager> 
     <ScrollViewer x:Name="PART_ContentHost" 
         BorderThickness="0" 
         IsTabStop="False" 
         Background="{x:Null}"/> 
    </Grid> 
</ControlTemplate> 

<Style x:Key="RegularTextBox" TargetType="{x:Type TextBox}"> 
    <Setter Property="Foreground" Value="{StaticResource NormalBrush}"/> 
    <Setter Property="Template" Value="{StaticResource RegularTextBoxTemplate}"/> 
</Style> 

Мои пытались раскадровки:

<ColorAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentHost" 
        Storyboard.TargetProperty="(Foreground).(SolidColorBrush.Color)"> 
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" /> 
</ColorAnimationUsingKeyFrames> 

<ColorAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentHost" 
       Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"> 
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" /> 
</ColorAnimationUsingKeyFrames> 

<ColorAnimationUsingKeyFrames Storyboard.TargetName="PART_ContentHost" 
      Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"> 
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" /> 
</ColorAnimationUsingKeyFrames> 

<ColorAnimationUsingKeyFrames 
        Storyboard.TargetProperty="(Foreground).(SolidColorBrush.Color)"> 
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" /> 
</ColorAnimationUsingKeyFrames> 

<ColorAnimationUsingKeyFrames 
       Storyboard.TargetProperty="(TextBox.Foreground).(SolidColorBrush.Color)"> 
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" /> 
</ColorAnimationUsingKeyFrames> 

<ColorAnimationUsingKeyFrames 
       Storyboard.TargetProperty="(Control.Foreground).(SolidColorBrush.Color)"> 
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" /> 
</ColorAnimationUsingKeyFrames> 

<ColorAnimationUsingKeyFrames 
      Storyboard.TargetProperty="(TextElement.Foreground).(SolidColorBrush.Color)"> 
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" /> 
</ColorAnimationUsingKeyFrames> 

Ни один из них не работает. Есть идеи? Возможно ли это?

+0

Вы пытаетесь анимировать 'SolidColorBrush'' PART_ContentHost', однако он не содержит кисти. Вы пытались присвоить некоторую начальную кисть? (И куда идет ваш контент?) – Vlad

+0

@ Vlad Да. См. Обновленный вопрос. –

+0

Ну, я все еще вижу ''. Итак, вы пытаетесь анимировать свойство на объекте «null», верно? – Vlad

ответ

5

Ну, спасибо всем, кто пытался мне помочь, я нашел ответ. Кажется, когда мы устанавливаем свойство TextBox.Foreground ресурсу, раскадровка не может его анимировать. Итак, стиль должен быть примерно таким:

<Style x:Key="RegularTextBox" TargetType="{x:Type TextBox}"> 
    <Setter Property="Foreground"> 
     <Setter.Value> 
      <SolidColorBrush Color="{DynamicResource NormalColor}"/> 
     </Setter.Value> 
    </Setter> 
    <Setter Property="Template" Value="{StaticResource RegularTextBoxTemplate}"/> 
</Style> 

Это была единственная проблема, с которой я столкнулся. Но есть заметка для запоминания. Когда мы хотим нацелить шаблонного родителя в раскадровку, нет необходимости связываться с ним. Нам просто нужно оставить его:

<!-- It's not necessary to set Storyboard.TargetName in storyboard --> 
<!-- It will automatically target the TemplatedParent --> 
<ColorAnimationUsingKeyFrames 
       Storyboard.TargetProperty="(TextBox.Foreground).(SolidColorBrush.Color)"> 
    <EasingColorKeyFrame KeyTime="0" Value="{DynamicResource MouseOverColor}" /> 
</ColorAnimationUsingKeyFrames> 

Это работает для меня.


Here является рабочим примером.

+2

Я не знаю, как вам удалось это сделать. Для меня это все равно приводит к неизменному исключению цвета. – nmclean

+0

@nmclean Моя ошибка. Используйте '(TextBox.Foreground). (SolidColorBrush.Color)' как свойство target. Он отлично работает –

+1

Я не могу заставить это работать ... Я получаю неизменную ошибку, с которой мне пришлось работать в своем ответе. –

9

Это было более проблематично, чем я думал. Вот мой первоначальный ответ:


Это определенно возможно - для этого предназначены классы ColorAnimationXXX.

Ваш код очень похож на пример кода here, который анимирует цвет с помощью ColorAnimation. Свойство в примере берет кисть (точно так же, как TextBox.Foreground), которая определена в XAML и задана имя, чтобы анимация могла легко ссылаться на анимацию.

Так что в вашем случае уместна код будет:

<VisualState Name="..."> 
    <Storyboard> 
     <ColorAnimation To="Green" 
         Storyboard.TargetName="tbBrush" 
         Storyboard.TargetProperty="Color"/> 
    </Storyboard> 
</VisualState> 

и:

<TextBox.Foreground> 
    <SolidColorBrush x:Name="tbBrush" Color="#FF666666"/> 
</TextBox.Foreground> 

Это все было очень хорошо, в теории, пока я не понял, что это не работает в стиле. В то время как Background свойство сетки в стиле легко анимируемое, что-то вроде:

Storyboard.TargetProperty="(Grid.Background).(SolidColorBrush.Color)" 

это значительно сложнее найти недвижимость анимировать, что будет иметь эффект на переднем плане текста. Первоначально я попробовал TextElement.Foreground, что кажется интуитивным, и я смог установить это свойство на уровнях Grid и ScrollViewer, которые, как я ожидал, повлияют на все дочерние объекты внизу - включая любой объект, который находится на нижнем уровне, который содержит текст текстового поля. Мое предположение заключалось в том, что содержимое TextBox будет внутренне установлено в TextBlock, которое будет подчиняться значению установленного на нем свойства Foreground. Похоже, что мое предположение было неправильным, а содержимое PART_ContentHost ScrollViewer задано логикой управления в TextBox для объекта более низкого уровня, который не подчиняется ни одному из свойств зависимостей Foreground в дереве объектов между верхним уровнем TextBox и сам.

Проблема заключается в том, как установить свойство Foreground для TextBox в стиле стилизованного TextBox. Для тестирования я попытался установить это с привязкой TwoWay TemplatedParent. Я думаю, что я получил PropertyPath для цвета SolidColorBrush, но он все еще не работал, поскольку свойство Color было по-видимому неизменным в этот момент. Я считаю, что этот вопрос документирован here.

В дополнение к тому, что он не работает, установка свойства Foreground внутренне не показалась правильной, поскольку внешние потребители ожидали бы контроля над стоимостью этого свойства. Итак, учитывая, что Foreground из TextBox не будет подчиняться чему-либо в стиле, я пришел к выводу, что функциональность лучше всего реализуется с помощью вложенного TextBox в стиле TextBox. Внешний стиль содержит диспетчер состояний и большую часть макета, тогда внутренний TextBox имеет свой собственный стиль и шаблон управления, который предназначен для отображения текстового бита. Внешний стиль позволяет установить свойство Foreground внутреннего TextBox, которое будет подчиняться внутреннему, и, главное, внешнее может установить это значение в диспетчере состояний.

<ControlTemplate x:Key="RegularTextBoxTemplate" TargetType="{x:Type TextBox}"> 
    <Grid> 
     <VisualStateManager.VisualStateGroups> 
      <VisualStateGroup x:Name="CommonStates"> 
       <VisualStateGroup.Transitions> 
        <VisualTransition GeneratedDuration="0:0:0.1"/> 
       </VisualStateGroup.Transitions> 
       <VisualState x:Name="Normal"/> 
       <VisualState x:Name="MouseOver"> 
        <Storyboard> 
         <ColorAnimation To="HotPink" 
          Storyboard.TargetName="InternalTextBox" 
          Storyboard.TargetProperty="(TextBox.Foreground).(SolidColorBrush.Color)"/> 
        </Storyboard> 
       </VisualState> 
      </VisualStateGroup> 
     </VisualStateManager.VisualStateGroups> 
     <TextBox Foreground="Black" Text="{TemplateBinding Text}" x:Name="InternalTextBox"> 
      <TextBox.Style> 
       <Style TargetType="{x:Type TextBox}"> 
        <Setter Property="Template"> 
         <Setter.Value> 
          <ControlTemplate TargetType="{x:Type TextBox}"> 
           <Grid Background="{x:Null}"> 
            <ScrollViewer x:Name="PART_ContentHost" 
             BorderThickness="0" 
             IsTabStop="False" 
             Background="{x:Null}" /> 
           </Grid> 
          </ControlTemplate> 
         </Setter.Value> 
        </Setter> 
       </Style> 
      </TextBox.Style> 
     </TextBox> 
    </Grid> 
</ControlTemplate> 

<Style x:Key="RegularTextBox" TargetType="{x:Type TextBox}"> 
    <Setter Property="Template" Value="{StaticResource RegularTextBoxTemplate}"/> 
</Style> 

мне было бы интересно услышать комментарии других людей на этом подходе, и есть ли какие-либо проблемы с ним, что я не учел. Основываясь на моих попытках решить проблему и отслеживать результирующее приложение, это самое простое решение, которое я вижу на данный момент.

+0

+1 Спасибо за помощь –

+0

Выполняется ли это, если вы устанавливаете 'Foreground =" {TemplateBinding Foreground} "' на внутреннем TextBox? В текущей версии, кажется, нет способа установить «нормальный» цвет. – nmclean

+0

Я был доволен тем, что был честным, поэтому я не проверял - я думаю, что он будет работать нормально, а если нет, то переднего плана внутреннего текстового поля можно установить в других состояниях диспетчера визуальных состояний. –

2

Вы можете связать Storyboard.Target с TemplatedParent:

<ColorAnimationUsingKeyFrames 
     Storyboard.Target="{Binding RelativeSource={RelativeSource TemplatedParent}}" 
     Storyboard.TargetProperty="(TextBox.Foreground).(SolidColorBrush.Color)"> 
    <EasingColorKeyFrame KeyTime="0" Value="{StaticResource MouseOverColor}" /> 
</ColorAnimationUsingKeyFrames> 

К сожалению, я мог получить только эту работу, когда нормальный план кисть не набор в стиле, так и непосредственно установлен на элементе TextBox:

<TextBox Foreground="{StaticResource NormalBrush}" Style="{StaticResource RegularTextBox}" /> 

Если он установлен в стиле, вызывая состояние MouseOver бросает «не удается оживить„(0). (1)“на экземпляре неизменного объекта.»Редактировать: Это также происходит, если вы снова установите переднюю часть TextBox после ее инициализации.

+0

+1 Спасибо за помощь –