我有ContentControl
我正在使用DataTemplate
设置样式。我希望能够在ContentControl
之外定义动画,以动画DataTemplate
中的元素。这个XAML是我的场景的一个简单的小例子:
<UserControl x:Class="StoryboardTesting.Stage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d">
<UserControl.Resources>
<DataTemplate x:Key="MyControlTemplate">
<StackPanel>
<TextBlock x:Name="TheBlock1" Text="Foo!" />
<TextBlock x:Name="TheBlock2" Text="Bar!" />
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup Name="ValueStates">
<VisualState Name="ToState">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MyContentControl"
Storyboard.TargetProperty="(UIElement.Opacity)"
Duration="0:0:1"
To="0" />
</Storyboard>
</VisualState>
<VisualState Name="FromState" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid>
<Canvas>
<ContentControl x:Name="MyContentControl"
ContentTemplate="{StaticResource MyControlTemplate}" />
</Canvas>
</Grid>
</UserControl>
我希望动画能够通过位置或名称来定位模板中的TextBox
(而不是“MyContentControl”)。我正在UserControl
的代码隐藏中启动动画,通过这样的调用:
VisualStateManager.GoToElementState(this, "ToState", true);
当我运行它(用“TheBlock”替换“MyContentControl”)时,我得到以下内容:
InvalidOperationException:在'StoryboardTesting.Stage'的名称范围内找不到'TheBlock1'名称。
哪个有道理。有没有办法使用属性名称解决任何一个块?我需要避免代码隐藏,因为这是在运行时生成的XAML。
答案 0 :(得分:1)
我强烈建议您在使用WPF项目时学习使用Blend。虽然键盘技巧的XAML确实很有用,但Blend也非常有用。我花了大约5分钟为你构建以下示例,它是一个DataTemplate
,它有状态。
(首先我创建了一个空的DataTemplate
,然后我在Blend中编辑了)
用户可以按下底部的任意2个按钮,当前状态将会改变。
正如您在下面看到的那样,行为被证明对处理状态非常有帮助,完全没有代码隐藏。
XAML:
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:wpfApplication3="clr-namespace:WpfApplication3"
Title="MainWindow"
Width="525"
Height="350">
<Window.Resources>
<wpfApplication3:MyObject x:Key="MyObject1" />
<DataTemplate x:Key="Template1" DataType="wpfApplication3:MyObject">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="37*" />
<RowDefinition Height="13*" />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="VisualStateGroup">
<VisualState x:Name="Red">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="button" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Red" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Green">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="button" Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<EasingColorKeyFrame KeyTime="0" Value="Lime" />
</ColorAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Button x:Name="button"
Grid.RowSpan="1"
Grid.ColumnSpan="2"
Width="100"
Height="100"
Margin="2"
Content="Button"
FontSize="26.667" />
<Button Grid.Row="1"
Width="Auto"
Margin="2"
Content="State1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction StateName="Red" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
<Button Grid.Row="1"
Grid.Column="1"
Width="Auto"
Margin="2"
Content="State2">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:GoToStateAction StateName="Green" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<ContentControl Content="{StaticResource MyObject1}" ContentTemplate="{StaticResource Template1}" />
</Grid>
</Window>
代码隐藏:
namespace WpfApplication3
{
public partial class MainWindow
{
public MainWindow() {
InitializeComponent();
}
}
internal class MyObject
{
public string Category { get; set; }
public int Value { get; set; }
}
}
修改强>
要回答您的问题,这些州属于DataTemplate
;在它之外定义这些状态并没有任何意义,正如你所经历的那样甚至是不可能的,这是有充分理由的!
想象一下,你在两个不同的地方使用这个模板,它们会共享相同的状态吗?当然没有,因此必须在其中定义状态,而不是在外部。