在动画制作之前,StackPanel上的FluidMoveBehavior闪烁

时间:2015-09-02 19:56:27

标签: c# wpf xaml blend

我有一个ItemsControl附加FluidMoveBehavior就像这样:

<ScrollViewer VerticalScrollBarVisibility="Auto">
    <ItemsControl ItemsSource="{Binding RequirementsSource}" ItemTemplateSelector="{StaticResource RequirementTemplateSelector}">
        <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
                <StackPanel IsItemsHost="True">
                    <i:Interaction.Behaviors>
                        <ic:FluidMoveBehavior AppliesTo="Children" Duration="0:0:00.5" Tag="DataContext">
                            <ic:FluidMoveBehavior.EaseX>
                                <BackEase EasingMode="EaseInOut" Amplitude="0.5"/>
                            </ic:FluidMoveBehavior.EaseX>
                            <ic:FluidMoveBehavior.EaseY>
                                <BackEase EasingMode="EaseInOut" Amplitude="0.5"/>
                            </ic:FluidMoveBehavior.EaseY>
                            </ic:FluidMoveBehavior>
                    </i:Interaction.Behaviors>
                </StackPanel>
            </ItemsPanelTemplate>
        </ItemsControl.ItemsPanel>
    </ItemsControl>
</ScrollViewer>

当项目更改其排序顺序时,它们会进行动画处理,但首先将项目排序为好像没有附加FluidMoveBehavior,然后排序。整个事情发生得足够快,在动画开始之前看起来像是一个闪烁。

ItemsControl ItemsSource如下所示:

RequirementsSource = new ListCollectionView(Requirements);
ICollectionViewLiveShaping live = (ICollectionViewLiveShaping)RequirementsSource;
live.IsLiveSorting = True;
live.IsLiveFiltering = True;
live.LiveSortingProperties.Add("Rank");
live.LiveFilteringProperties.Add("Owner");
RequirementsSource.SortDescriptions.Add(
    new SortDescription("Rank", ListSortDirection.Ascending)
);
RequirementsSource.Filter = _filterPred;

排序由以下方法触发:

private void SwapRanks(SwapArgs args)
{
    IPropertyRequirement first = args.Warning.Requirements
        .First(r => r.Rank == args.RankToSwap);
    IPropertyRequirement second = args.Warning.Requirements
        .First(r => r.Rank == args.SwapWith);

    int temp = first.Rank;
    first.Rank = second.Rank;
    second.Rank = temp;

    RequirementsSource.Refresh();
}

有没有人知道造成这种“闪烁”的原因是什么以及我可以做些什么来阻止它?

1 个答案:

答案 0 :(得分:1)

从您的代码中删除RequirementsSource.Refresh();行。

由于您正在使用生命周期,因此当Requirement.Rank更改时会启动动画(触发PropertyChanged事件)。但是当你调用refresh时,它会使用Reset参数引发CollectionChanged并强制列表框刷新。

修改

public class MainWindowViewModel 
{
    ObservableCollection<Requirement> requirements;
    public MainWindowViewModel()
    {
        requirements = new ObservableCollection<Requirement>(Enumerable
            .Range(0, 10)
            .Select(i => new Requirement {Rank = 10 - i, Name = "Item " + i}));

        RequirementsSource = new ListCollectionView(requirements);
        var live = (ICollectionViewLiveShaping)RequirementsSource;
        live.IsLiveSorting = true;
        live.IsLiveFiltering = true;
        live.LiveSortingProperties.Add("Rank");
        RequirementsSource.SortDescriptions.Add(
            new SortDescription("Rank", ListSortDirection.Ascending)
        );
        ReorderCommand = new DelegateCommand(Reorder);
    }

    public ListCollectionView RequirementsSource { get; set; }
    public DelegateCommand ReorderCommand { get; private set; }

    private void Reorder()
    {
        for (int i = 0; i < requirements.Count - 1; i += 2)
        {
            var temp = requirements[i].Rank;
            requirements[i].Rank = requirements[i + 1].Rank;
            requirements[i + 1].Rank = temp;
        }
    }
}
   
public class Requirement : BindableBase
{
    private double _rank;

    public double Rank
    {
        get { return _rank; }
        set { SetProperty(ref _rank, value); }
    }

    public string Name { get; set; }
}