1

私はまた少し困惑していて、誰かが助けてくれることを望んでいました。長いコードを前もってお詫びします。

問題-期待どおりに起動を開始するDataTriggerがありますが、最終的に失敗し、理由を理解できません。提供されている例では、Canvasの周りで長方形を移動します。ボタンをクリックするたびに、この順序でボタンが移動します。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>

コードビハインド;

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()
    {
    }
}
4

1 に答える 1

1

ここでの問題は、最終的に、アニメーションが実際にはプロパティCanvas.LeftCanvas.Topプロパティの値を変更しないという事実に帰着します。アニメーションから取得した値は、データバインディングを介して取得した値を上書きするため、これらはそうしているように見えます。

Canvas.Left各アニメーションが終了すると、アニメーションは'または依存関係プロパティの値を'Canvas.Top最終値に保持します。この「保持」値は、依存関係プロパティの値を取得した場合に返される値であり、データバインディングを介して設定された値をオーバーライドします。2番目のアニメーションを開始すると、依存関係プロパティの値は、前のアニメーションの保持された値から作業することによって取得されます。ますます多くのアニメーションが発生するにつれて、WPFは、ますます多くのアニメーションのチェーンをさかのぼって、長方形の位置を決定する必要があります。

すべてを実行した後、最後の(NW)アニメーションのみが実行される理由はわかりません。おそらく、依存関係プロパティ値の優先順位と関係があります。このページでは、依存関係プロパティに複数のアニメーションがある場合に何が起こるかについては説明していませんが、この状況では、そのプロパティで開始する最後のアニメーションが優先されると思います。が起動していると思われDataTriggerますが、何らかの理由でWPF依存関係プロパティシステムが「オーバーライドされた」アニメーションからの値を無視しています。

このような一連のアニメーションは避けることをお勧めします。代わりに、オブジェクトを変更して、プロパティPersonを追加するなどして、オブジェクトがキャンバス上のどこにあるかを追跡します。次に、これらのプロパティにバインドできます。メソッドは、これらのプロパティの値を、アニメーションがそれらを移動する場所にも設定する必要があります。プロパティの値を変更した後にこれを行います。最後に、それぞれに設定して、アニメーションが最終値を「保持」しないようにします。LeftTopCanvas.LeftCanvas.TopDoNextMoveUI_DirectionOfMovementFillBehavior="Stop"DoubleAnimation

アニメーション化された値はローカルで設定された値よりも優先されるため、アニメーションの開始時にプロパティ値を設定することは問題ありませんLeftTopアニメーションの実行中、アニメーション化された値はCanvas.LeftCanvas.Topデータバインディングを介して設定された値よりも優先されます。アニメーションが終了すると、アニメーションはプロパティCanvas.LeftCanvas.Top依存関係プロパティの保持を解除し、長方形の位置はデータバインディングを介して取得された状態に戻ります。運が良ければ、この場所はアニメーションの最後と同じになります。

于 2013-03-27T14:35:04.550 に答える