自定义拖放UWP

时间:2019-01-16 17:14:47

标签: c# listview uwp

我需要创建一个自定义的拖放。我创建了两个列表视图,并且在第一个列表中通过指针按下事件创建了带有自定义图像的拖动。唯一缺少的是:成功将事件拖动或事件指针输入到第二个列表视图的项目的网格中。这是行不通的,因为当发生这种情况时,移动的事件仍然处于活动状态。

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:

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);
    }
}

我如何使拖动事件起作用,或者在这种情况下,即使在移动图像并且第一个列表视图的移动事件处于活动状态时,也要在第二个列表视图中输入指针?

总是提前谢谢!

1 个答案:

答案 0 :(得分:0)

如果要在UWP中实现拖放操作,则需要执行以下步骤:

  
      
  1. 通过将其CanDrag属性设置为true启用在元素上拖动。
  2.   
  3. 构建数据包。系统会自动处理图像和文本,但是对于其他内容,您需要处理DragStarted和DragCompleted事件,并使用它们来构造自己的数据包。
  4.   
  5. 通过将所有可以接收放置内容的元素的AllowDrop属性设置为true来启用放置。
  6.   
  7. 处理DragOver事件以使系统知道元素可以接收的拖动操作类型。
  8.   
  9. 处理Drop事件以接收被丢弃的内容。
  10.   

更多信息,请参阅Drag and Drop文档。

这是UWP官员Drag and drop sample,为您提供详细信息。