我有一个简单的MainWindow,它带有一个包含Grid的根网格和一个带有Button的单元格,并且根网格还包含一个overlay控件(该控件具有部分透明的背景和一些短文字,例如Drop here ...) 。当用户在窗口上拖动文件时,此全窗口叠加层会以淡入淡出的动画显示。问题是我的动画没有完成,几乎没有开始,并在用户将文件拖到窗口上时重复播放。
我不确定下一步要去哪里。 DropOverlay类和XAML看起来不错。我认为问题出在d&d事件处理中。当我使用IsHitTestVisible =“ False”时,如果没有动画,它似乎会更好地工作。
<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>
没什么特别的。
<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;
}
}
预期结果:当用户开始在窗口上拖动文件时,淡入动画将运行并结束一次。
实际结果:淡入动画没有结束,它一遍又一遍地开始,一直运行到几乎看不到覆盖层的位置。有时候,当我用鼠标离开窗口并拖动叠加层时,它会很好地淡入(但不是在适当的时候),有时不是。
答案 0 :(得分:1)
发现它只是删除您在 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;
}
}
用于淡入/淡出动画
问题是动画时您的UserControl设置为“折叠” =>我们需要“连接的动画”(一个接一个的动画)
在我们的情况下,我们需要一些独立的布尔值:我选择了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>