我又一次被难住了,希望有人能帮上忙。提前道歉,代码太长了。
问题-我有一个DataTrigger,它按预期启动,但它最终失败了,我不知道为什么。在提供的示例中,它在画布周围移动一个矩形。每次单击按钮都会按以下顺序移动它: N、NE、E、SE、S、SW、W、NW。然后,它再次启动序列,从N开始。一旦第一个序列完成,它就不会向北移动。它只会再次向西北移动(最后一步成功)。
触发DataTrigger的属性正在更新。
谢谢
XAML;
<Window.Resources>
<Style x:Key="TestRectStyle" TargetType="{x:Type Rectangle}">
<Style.Triggers>
<DataTrigger Binding="{Binding UI_DirectionOfMovement}" Value="North">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" By="-50" Duration="0:0:0.8" AutoReverse="False" />
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" By="0" Duration="0:0:0.8" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding UI_DirectionOfMovement}" Value="NorthEast">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" By="-50" Duration="0:0:0.8" AutoReverse="False" />
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" By="50" Duration="0:0:0.8" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding UI_DirectionOfMovement}" Value="East">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" By="0" Duration="0:0:0.8" AutoReverse="False" />
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" By="50" Duration="0:0:0.8" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding UI_DirectionOfMovement}" Value="SouthEast">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" By="50" Duration="0:0:0.8" AutoReverse="False" />
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" By="50" Duration="0:0:0.8" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding UI_DirectionOfMovement}" Value="South">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" By="50" Duration="0:0:0.8" AutoReverse="False" />
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" By="0" Duration="0:0:0.8" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding UI_DirectionOfMovement}" Value="SouthWest">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" By="50" Duration="0:0:0.8" AutoReverse="False" />
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" By="-50" Duration="0:0:0.8" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding UI_DirectionOfMovement}" Value="West">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" By="0" Duration="0:0:0.8" AutoReverse="False" />
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" By="-50" Duration="0:0:0.8" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding UI_DirectionOfMovement}" Value="NorthWest">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Top)" By="-50" Duration="0:0:0.8" AutoReverse="False" />
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)" By="-50" Duration="0:0:0.8" AutoReverse="False" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
<DataTemplate x:Key="TestDataTemplate01" DataType="BO:MyPerson">
<Canvas Width="1000" Height="1000" Background="Transparent">
<Rectangle Width="50" Height="50" Fill="Red" Style="{StaticResource TestRectStyle}" Canvas.Top="300" Canvas.Left="300" />
</Canvas>
</DataTemplate>
</Window.Resources>
<Canvas Width="1000" Height="1000">
<ItemsControl Name="ic_People" ItemTemplate="{StaticResource TestDataTemplate01}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas Width="1000" Height="1000" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
<Button Canvas.Right="0" Click="Button_Click_1" Width="120">Next Move</Button>
</Canvas>Codebehind;
public partial class Window1 : Window
{
private ObservableCollection<MyPerson> _personList = new ObservableCollection<MyPerson>();
public Window1()
{
InitializeComponent();
MyPerson person1 = new MyPerson();
_personList.Add(person1);
ic_People.ItemsSource = _personList;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
DoNextMove();
}
private int debugDirection = 0;
private void DoNextMove()
{
if (debugDirection > 15)
debugDirection = 0;
_personList[0].MoveOneTile(debugDirection);
debugDirection += 2; // increase by 2 to as I've not implemented the odd numbers yet
}
}MyPerson代码;
public class MyPerson : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
private string _dirMov = "";
public string UI_DirectionOfMovement
{
get { return _dirMov; }
set
{
_dirMov = value;
OnPropertyChanged("UI_DirectionOfMovement");
}
}
public void MoveOneTile(int directionToMove)
{
this.UI_DirectionOfMovement = "clear"; // clearing it first forces an update
switch (directionToMove)
{
case 0: { this.UI_DirectionOfMovement = "North"; break; }
case 2: { this.UI_DirectionOfMovement = "NorthEast"; break; }
case 4: { this.UI_DirectionOfMovement = "East"; break; }
case 6: { this.UI_DirectionOfMovement = "SouthEast"; break; }
case 8: { this.UI_DirectionOfMovement = "South"; break; }
case 10: { this.UI_DirectionOfMovement = "SouthWest"; break; }
case 12: { this.UI_DirectionOfMovement = "West"; break; }
case 14: { this.UI_DirectionOfMovement = "NorthWest"; break; }
default: { throw new Exception(); }
}
}
public MyPerson()
{
}
}发布于 2013-03-27 22:35:05
这里的问题最终归结为动画实际上并不改变Canvas.Left和Canvas.Top属性的值。它们看起来只是这样做,因为从动画中获得的值覆盖了通过数据绑定获得的值。
在每个动画完成后,动画将Canvas.Left或Canvas.Top依赖属性的值“保持”为其最终值。如果您获取依赖属性的值,则此“保留”值将返回,并且它将覆盖通过数据绑定设置的任何值。当您开始第二个动画时,dependency属性的值是通过计算前一个动画的保留值来获得的。随着越来越多的动画发生,WPF必须通过返回一系列越来越多的动画来确定矩形的位置。
我不能说为什么只有最后一个(NW)动画在你运行完所有的动画之后才运行。这很可能与dependency property value precedence有关。这个页面没有说明如果一个依赖属性上有多个动画会发生什么,但在这种情况下,我会假设在该属性上启动的最后一个动画优先。我怀疑DataTrigger正在触发,但由于某种原因,WPF依赖属性系统忽略了来自“覆盖”动画的值。
我建议避免像这样的一系列动画。相反,可以更改Person对象以跟踪它们在画布上的位置,例如,通过添加Left和Top属性。然后,可以将Canvas.Left和Canvas.Top绑定到这些属性。DoNextMove方法还应将这些属性的值设置为动画将它们移动到的位置。在更改UI_DirectionOfMovement属性的值之后执行此操作。最后,通过在每个DoubleAnimation上设置FillBehavior="Stop"来阻止动画‘保留’它们的最终值。
由于动画值优先于本地设置的值,因此在动画开始时设置Left和Top的属性值不成问题。在动画运行时,Canvas.Left和Canvas.Top的动画值优先于通过数据绑定设置的任何值。动画完成后,动画将解除对Canvas.Left和Canvas.Top依赖项属性的控制,矩形的位置将恢复为通过数据绑定获取。如果幸运的话,这个位置将与动画结束时的位置相同。
https://stackoverflow.com/questions/15657822
复制相似问题