简体   繁体   English

自定义拖放UWP

[英]Custom Drag And Drop UWP

I need to create a custom drag and drop. 我需要创建一个自定义的拖放。 I created two listview and in the first one through the pointer pressed event I created the drag with a customized image. 我创建了两个列表视图,并且在第一个列表中通过指针按下事件创建了带有自定义图像的拖动。 The only thing that is missing is: to succeed in having the event dragover or the event pointerentered in the grid of the item of the second listview. 唯一缺少的是:成功将事件拖动或事件指针输入到第二个列表视图的项目的网格中。 This does not work because when this should occur, the moved event is still active. 这是行不通的,因为当发生这种情况时,移动的事件仍处于活动状态。

MainPage.xaml: MainPage.xaml:

<Page
x:Class="Drag_And_Drop_Custom_UWP.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="using:Drag_And_Drop_Custom_UWP"
mc:Ignorable="d"
Loaded="Page_Loaded"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
    <local:DrugPosition x:Name="CoordinatesDrug"/>
</Page.Resources>
<Grid x:Name="BaseGrid">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <ListView x:Name="ListViewPerson" ItemsSource="{x:Bind ListPerson}" ItemContainerStyle="{StaticResource ListViewItemRevealStyleDrug}" Margin="50">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:Person">
                    <Grid x:Name="GridPerson" Background="Red" PointerPressed="GridPerson_PointerPressed">
                        <StackPanel Orientation="Vertical">
                            <TextBlock Text="{x:Bind Name}" Margin="5"/>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        <ListView x:Name="ListViewHeight" ItemsSource="{x:Bind ListHeight}" ItemContainerStyle="{StaticResource ListViewItemRevealStyleDrug}" Margin="50" Grid.Column="1">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="local:Characteristic">
                    <Grid x:Name="GridHeight" Background="Red" AllowDrop="True" 
                          PointerEntered="GridHeight_PointerEntered"
                          PointerExited="GridHeight_PointerExited"
                          DragEnter="GridHeight_DragEnter"
                          DragLeave="GridHeight_DragLeave">
                        <StackPanel Orientation="Vertical">
                            <TextBlock Text="{x:Bind PersonHeight}" Margin="5"/>
                        </StackPanel>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
    <Canvas x:Name="GridForDrop">
        <Grid x:Name="GridLetter" HorizontalAlignment="Left" Height="100" Margin="-128,10,0,0" VerticalAlignment="Top" Width="100" Background="#FF18AA30">
            <TextBlock Text="C" HorizontalAlignment="Center" VerticalAlignment="Center" Foreground="White" FontSize="72"/>
        </Grid>
        <Image x:Name="ImageToDrugOver" Canvas.Left="{x:Bind CoordinatesDrug.LeftDrugPosition, Mode=OneWay}" Canvas.Top="{x:Bind CoordinatesDrug.TopDrugPosition, Mode=OneWay}"/>
    </Canvas>
</Grid>

MainPage.xaml.cs: MainPage.xaml.cs:

public class Person
{
    public string Name { get; set; }
}
public class Characteristic
{
    public int PersonHeight { get; set; }
}
public class DrugPosition : INotifyPropertyChanged
{
    private double leftDrugPosition;
    public double LeftDrugPosition
    {
        get
        {
            return leftDrugPosition;
        }
        set
        {
            leftDrugPosition = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(LeftDrugPosition)));
        }
    }

    private double topDrugPosition;
    public double TopDrugPosition
    {
        get
        {
            return topDrugPosition;
        }
        set
        {
            topDrugPosition = value;
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TopDrugPosition)));
        }
    }
    public event PropertyChangedEventHandler PropertyChanged;
}
public sealed partial class MainPage : Page
{
    ObservableCollection<Person> ListPerson = new ObservableCollection<Person>();
    ObservableCollection<Characteristic> ListHeight = new ObservableCollection<Characteristic>();

    public MainPage()
    {
        this.InitializeComponent();
    }

    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        ListPerson.Add(new Person() { Name = "Person 1" });
        ListPerson.Add(new Person() { Name = "Person 2" });
        ListPerson.Add(new Person() { Name = "Person 3" });
        ListPerson.Add(new Person() { Name = "Person 4" });
        ListPerson.Add(new Person() { Name = "Person 5" });

        ListHeight.Add(new Characteristic() { PersonHeight = 100 });
        ListHeight.Add(new Characteristic() { PersonHeight = 200 });
        ListHeight.Add(new Characteristic() { PersonHeight = 100 });
        ListHeight.Add(new Characteristic() { PersonHeight = 200 });
        ListHeight.Add(new Characteristic() { PersonHeight = 100 });
    }

    private async void GridPerson_PointerPressed(object sender, PointerRoutedEventArgs e)
    {
        Grid GridPersona = sender as Grid;
        Point puntopressd = e.GetCurrentPoint(BaseGrid).Position;
        BitmapImage ImageToDrug = await LoadImageForDrug();
        CoordinatesDrug.LeftDrugPosition = puntopressd.X - 50;
        CoordinatesDrug.TopDrugPosition = puntopressd.Y - 50;
        ImageToDrugOver.Source = ImageToDrug;

        PointerEventHandler moved = null;
        moved = (s, args) =>
        {
            BaseGrid.CapturePointer(e.Pointer);
            Point puntomoved = e.GetCurrentPoint(BaseGrid).Position;
            CoordinatesDrug.LeftDrugPosition = puntomoved.X - 50;
            CoordinatesDrug.TopDrugPosition = puntomoved.Y - 50;

        };

        PointerEventHandler released = null;
        released = (s, args) =>
        {
            Point puntoreleas = e.GetCurrentPoint(BaseGrid).Position;
            ImageToDrugOver.Source = null;
            BaseGrid.PointerMoved -= moved;
            BaseGrid.PointerReleased -= released;
        };
        BaseGrid.PointerMoved += moved;
        BaseGrid.PointerReleased += released;
    }

    private async Task<BitmapImage> LoadImageForDrug()
    {
        RenderTargetBitmap rtb = new RenderTargetBitmap();
        await rtb.RenderAsync(GridLetter);

        InMemoryRandomAccessStream stream = new InMemoryRandomAccessStream();
        var buffer = await rtb.GetPixelsAsync();

        BitmapImage img = new BitmapImage();
        var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.PngEncoderId, stream);
        encoder.SetPixelData(
            BitmapPixelFormat.Bgra8,
            BitmapAlphaMode.Straight,
            (uint)rtb.PixelWidth,
            (uint)rtb.PixelHeight,
            DisplayInformation.GetForCurrentView().LogicalDpi,
            DisplayInformation.GetForCurrentView().LogicalDpi,
            buffer.ToArray());
        await encoder.FlushAsync();
        await img.SetSourceAsync(stream);
        return img;
    }

    private void GridHeight_PointerEntered(object sender, PointerRoutedEventArgs e)
    {
        Grid GridHeight = sender as Grid;
        GridHeight.Background = new SolidColorBrush(Colors.Yellow);
    }

    private void GridHeight_PointerExited(object sender, PointerRoutedEventArgs e)
    {
        Grid GridHeight = sender as Grid;
        GridHeight.Background = new SolidColorBrush(Colors.Red);
    }

    private void GridHeight_DragEnter(object sender, DragEventArgs e)
    {
        Grid GridHeight = sender as Grid;
        GridHeight.Background = new SolidColorBrush(Colors.Yellow);
    }

    private void GridHeight_DragLeave(object sender, DragEventArgs e)
    {
        Grid GridHeight = sender as Grid;
        GridHeight.Background = new SolidColorBrush(Colors.Red);
    }
}

How could I make the dragover event work, or rather in this case pointer entered (in the second listview) even while moving the image and the moved event of the first listview is active? 我如何使拖动事件起作用,或者在这种情况下,即使在移动图像并且第一个列表视图的移动事件处于活动状态时,也要在第二个列表视图中输入指针?

Always thanks in advance! 总是提前谢谢!

If you want to implement Drag and Drop operation in UWP, you need to do the following steps: 如果要在UWP中实现拖放操作,则需要执行以下步骤:

  1. Enable dragging on an element by setting its CanDrag property to true. 通过将其CanDrag属性设置为true启用在元素上拖动。
  2. Build the data package. 构建数据包。 The system handles images and text automatically, but for other content, you'll need to handle the DragStarted and DragCompleted events and use them to construct your own data package. 系统会自动处理图像和文本,但是对于其他内容,您需要处理DragStarted和DragCompleted事件,并使用它们来构造自己的数据包。
  3. Enable dropping by setting the AllowDrop property to true on all the elements that can receive dropped content. 通过在所有可以接收放置内容的元素上将AllowDrop属性设置为true来启用放置。
  4. Handle the DragOver event to let the system know what type of drag operations the element can receive. 处理DragOver事件,以使系统知道元素可以接收的拖动操作类型。
  5. Process the Drop event to receive the dropped content. 处理Drop事件以接收删除的内容。

More information, please see Drag and Drop document. 详细信息,请参阅拖放文档。

Here's the UWP official Drag and drop sample for your details. 这是UWP官方拖放示例,供您详细了解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM