首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >EventTrigger有时无法触发

EventTrigger有时无法触发
EN

Stack Overflow用户
提问于 2013-03-27 19:34:13
回答 1查看 470关注 0票数 1

我又一次被难住了,希望有人能帮上忙。提前道歉,代码太长了。

问题-我有一个DataTrigger,它按预期启动,但它最终失败了,我不知道为什么。在提供的示例中,它在画布周围移动一个矩形。每次单击按钮都会按以下顺序移动它: N、NE、E、SE、S、SW、W、NW。然后,它再次启动序列,从N开始。一旦第一个序列完成,它就不会向北移动。它只会再次向西北移动(最后一步成功)。

触发DataTrigger的属性正在更新。

谢谢

XAML;

代码语言:javascript
复制
<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;

代码语言:javascript
复制
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代码;

代码语言:javascript
复制
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()
    {
    }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-03-27 22:35:05

这里的问题最终归结为动画实际上并不改变Canvas.LeftCanvas.Top属性的值。它们看起来只是这样做,因为从动画中获得的值覆盖了通过数据绑定获得的值。

在每个动画完成后,动画将Canvas.LeftCanvas.Top依赖属性的值“保持”为其最终值。如果您获取依赖属性的值,则此“保留”值将返回,并且它将覆盖通过数据绑定设置的任何值。当您开始第二个动画时,dependency属性的值是通过计算前一个动画的保留值来获得的。随着越来越多的动画发生,WPF必须通过返回一系列越来越多的动画来确定矩形的位置。

我不能说为什么只有最后一个(NW)动画在你运行完所有的动画之后才运行。这很可能与dependency property value precedence有关。这个页面没有说明如果一个依赖属性上有多个动画会发生什么,但在这种情况下,我会假设在该属性上启动的最后一个动画优先。我怀疑DataTrigger正在触发,但由于某种原因,WPF依赖属性系统忽略了来自“覆盖”动画的值。

我建议避免像这样的一系列动画。相反,可以更改Person对象以跟踪它们在画布上的位置,例如,通过添加LeftTop属性。然后,可以将Canvas.LeftCanvas.Top绑定到这些属性。DoNextMove方法还应将这些属性的值设置为动画将它们移动到的位置。在更改UI_DirectionOfMovement属性的值之后执行此操作。最后,通过在每个DoubleAnimation上设置FillBehavior="Stop"来阻止动画‘保留’它们的最终值。

由于动画值优先于本地设置的值,因此在动画开始时设置LeftTop的属性值不成问题。在动画运行时,Canvas.LeftCanvas.Top的动画值优先于通过数据绑定设置的任何值。动画完成后,动画将解除对Canvas.LeftCanvas.Top依赖项属性的控制,矩形的位置将恢复为通过数据绑定获取。如果幸运的话,这个位置将与动画结束时的位置相同。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15657822

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档