Как сделать так, чтобы анимация постепенного появления этого наложения работала хорошо? - PullRequest
0 голосов
/ 19 июня 2019

У меня есть простое MainWindow с корневой сеткой, которая содержит сетку и ячейку с кнопкой, а корневая сетка также содержит элемент управления наложением (элемент управления с частично прозрачным фоном и некоторым коротким текстом, например, Drop здесь ...) , Это полноэкранное наложение отображается с постепенной анимацией, когда пользователь перетаскивает файл через окно. Проблема в том, что моя анимация не заканчивается, почти не запускается и повторяется, пока пользователь перетаскивает файл через окно.

Я не уверен, где искать дальше. Класс DropOverlay и XAML выглядят хорошо. Я думаю, что проблема в обработке событий D & D. Когда я использую IsHitTestVisible = "False", кажется, что он работает лучше, когда у меня нет анимации.

DropOverlay

1007 * XAML * <UserControl x:Class="cs_wpf_test_16.DropOverlay" 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" xmlns:local="clr-namespace:cs_wpf_test_16" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800" Style="{DynamicResource BorderStyle1}"> <UserControl.Resources> <Style TargetType="UserControl" x:Key="BorderStyle1"> <Style.Triggers> <Trigger Property="Visibility" Value="Visible"> <Trigger.EnterActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="Opacity" From="0" To="1" Duration="0:0:0.5"> </DoubleAnimation> </Storyboard> </BeginStoryboard> </Trigger.EnterActions> <Trigger.ExitActions> <BeginStoryboard> <Storyboard> <DoubleAnimation Storyboard.TargetProperty="Opacity" To="0" Duration="0:0:0.5"> </DoubleAnimation> </Storyboard> </BeginStoryboard> </Trigger.ExitActions> </Trigger> </Style.Triggers> </Style> </UserControl.Resources> <Border Background="#99000000"> <Viewbox> <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal" Margin="100" IsHitTestVisible="False"> <TextBlock Foreground="White" FontSize="50" Margin="15,0,0,0" Name="MyTextBlock">Drop Here...</TextBlock> </StackPanel> </Viewbox> </Border> </UserControl> Код-за

Ничего особенного.

MainWindow

XAML

<Window x:Class="cs_wpf_test_16.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:cs_wpf_test_16"
        mc:Ignorable="d"
        Title="MainWindow" Height="209.375" Width="317.969"
        PreviewDragEnter="MyWindow_DragEnter"
        PreviewDragLeave="MyWindow_DragLeave"
        PreviewDrop="MyWindow_Drop"
        AllowDrop="True">
    <Grid>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>
            <Grid.ColumnDefinitions>
                <ColumnDefinition/>
                <ColumnDefinition/>
            </Grid.ColumnDefinitions>

            <Button>Test</Button>
        </Grid>
        <local:DropOverlay Visibility="Collapsed" x:Name="MyDropOverlay"/>
    </Grid>
</Window>

Код-за

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    internal bool _DraggingOver = false;
    internal bool DraggingOver
    {
        get
        {
            return _DraggingOver;
        }
        set
        {
            if (_DraggingOver != value)
            {
                _DraggingOver = value;
                UpdateDropIndicator();
            }
        }
    }

    private void UpdateDropIndicator()
    {
        if (DraggingOver)
        {
            MyDropOverlay.Visibility = Visibility.Visible;
        }
        else
        {
            MyDropOverlay.Visibility = Visibility.Collapsed;
        }
    }

    private void MyWindow_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(DataFormats.FileDrop) &&
            !(e.Source is DropOverlay))
        {
            e.Effects = DragDropEffects.Link;

            var paths = e.Data.
                GetData(DataFormats.FileDrop) as string[];

            string path = paths[0];

            DraggingOver = true;

            e.Handled = true;
        }
        else
        {
            DraggingOver = false;

            //e.Handled = true;
        }
    }

    private void MyWindow_Drop(object sender, DragEventArgs e)
    {
        if (GetVisualParent<DropOverlay>(e.Source) == null)
        {
            e.Handled = true;
            return;
        }

        string[] paths = null;

        if (e.Effects != DragDropEffects.None &&
            e.Data.GetDataPresent(DataFormats.FileDrop))
        {
            paths = e.Data.
                GetData(DataFormats.FileDrop) as string[];
        }

        DraggingOver = false;

        if (paths != null)
        {
            MessageBox.Show(this, "Dropped.");
            e.Handled = true;
        }
    }

    private void MyWindow_DragLeave(object sender, DragEventArgs e)
    {
        if (GetVisualParent<DropOverlay>(e.Source) == null)
        {
            e.Handled = true;
            return;
        }

        Point p = Mouse.GetPosition(this);
        if (p.X < 0 || p.Y < 0 ||
            p.X > ActualWidth || p.Y > ActualHeight)
        {
            DraggingOver = false;

            e.Handled = true;
        }
    }

    public static T GetVisualParent<T>(object childObject) where T : System.Windows.Media.Visual
    {
        var child = childObject as System.Windows.DependencyObject;
        // iteratively traverse the visual tree
        while ((child != null) && !(child is T))
        {
            child = System.Windows.Media.VisualTreeHelper.GetParent(child);
        }
        return child as T;
    }
}

Ожидаемый результат: анимированная анимация запускается и заканчивается один раз, когда пользователь начинает перетаскивать файл через окно.

Фактический результат: анимация появления не заканчивается, она начинается снова и снова и продолжается до некоторой точки, где едва видно, что наложение там. Иногда, когда я покидаю окно мышью при перетаскивании оверлея, он плавно (но не в нужный момент), иногда нет.

Скриншоты

screenshot with the problem

screenshot with the drop overlay

1 Ответ

1 голос
/ 19 июня 2019

Нашел только удалить ваш другой случай в MyWindow_DragEnter

скопируйте приведенный ниже код и вставьте вместо вашего метода MyWindow_DragEnter.

в случаеВы ленивы:)

    private void MyWindow_DragEnter(object sender, DragEventArgs e)
    {
        if (e.Data.GetDataPresent(DataFormats.FileDrop) &&
            !(e.Source is DropOverlay))
        {
            e.Effects = DragDropEffects.Link;

            var paths = e.Data.
                GetData(DataFormats.FileDrop) as string[];

            string path = paths[0];

            DraggingOver = true;

            e.Handled = true;
        }

    }

ДЛЯ FADE IN / OUT АНИМАЦИЙ

Проблема в том, что ваш UserControl установлен на Collapsed при анимации => нам нужны "связанные анимации"(одна анимация за другой)

в нашем случае нам нужно некоторое независимое boolen: я взял Selector.IsSelected.

Измените ваш метод UpdateDropIndicator


        private void UpdateDropIndicator()
        {
            if (DraggingOver)
            {
                Selector.SetIsSelected(MyDropOverlay, true);
                //   MyDropOverlay.Visibility = Visibility.Visible;
            }
            else
            {
                Selector.SetIsSelected(MyDropOverlay, false);
                //MyDropOverlay.Visibility = Visibility.Collapsed;
            }
        }

и ваш xamlанимация


             <Trigger Property="Selector.IsSelected" Value="True">
                    <Trigger.EnterActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Opacity" 
                                                 From="0" 
                                                 To="1" 
                                                 Duration="0:0:0.5"/>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
                                                               Duration="0:0:0">
                                    <DiscreteObjectKeyFrame Value="{x:Static Visibility.Visible}" />
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.EnterActions>
                    <Trigger.ExitActions>
                        <BeginStoryboard>
                            <Storyboard>
                                <DoubleAnimation Storyboard.TargetProperty="Opacity" 
                                                 From="1" 
                                                 To="0" 
                                                 Duration="0:0:0.5"/>
                                <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Visibility"
                                                               Duration="0:0:0.5">
                                    <DiscreteObjectKeyFrame Value="{x:Static Visibility.Collapsed}" />
                                </ObjectAnimationUsingKeyFrames>
                            </Storyboard>
                        </BeginStoryboard>
                    </Trigger.ExitActions>
                </Trigger>

...