Пользовательский интерфейс WPF C # не отвечает при выполнении перетаскивания с помощью пользовательского элемента управления - PullRequest
0 голосов
/ 23 сентября 2018

Я застрял с проблемой перетаскивания C # wpf.Я создал очень простой проект, который включает в себя пользовательский элемент управления, пару классов для хранения данных и форму для размещения нескольких копий пользовательского элемента управления (с использованием привязанного ItemsControl).Когда я перетаскиваю элемент управления на форму, запускается перетаскивание, наблюдаемая коллекция обновляется, но пользовательский интерфейс не отражает изменения, и будущие события, похоже, не работают.Перемещение по кнопке добавления элемента даже не показывает эффект прокрутки.Конечно, я делаю что-то глупое, но я не могу понять, что это такое.

Код ниже (в основном из Пример Microsoft )

SimpleDataClass

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DragDropControl.Model
{
  public class SimpleDataClass : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;

    private string _groupName = string.Empty;
    private ObservableCollection<SimpleSubDataClass> _titles = new ObservableCollection<SimpleSubDataClass>();

    public string GroupName
    {
      get { return _groupName; }
      set
      {
        if (_groupName != value)
        {
          _groupName = value;
          RaisePropertyChangedEvent("GroupName");
        }
      }
    }

    public ObservableCollection<SimpleSubDataClass> Titles
    {
      get { return _titles; }
      set
      {
        if (_titles != value)
        {
          _titles = value;
          RaisePropertyChangedEvent("Titles");
        }
      }
    }

    private void RaisePropertyChangedEvent(string propertyName)
    {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}

SimpleSubDataClass

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace DragDropControl.Model
{
  public class SimpleSubDataClass : INotifyPropertyChanged
  {
    public event PropertyChangedEventHandler PropertyChanged;

    private string _title = string.Empty;

    public string Title
    {
      get { return _title; }
      set
      {
        if (_title != value)
        {
          _title = value;
          RaisePropertyChanged("Title");
        }
      }
    }

    private void RaisePropertyChanged(string propertyName)
    {
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    public SimpleSubDataClass(string title)
    {
      Title = title;
    }
  }
}

DDControl - XAML

<UserControl x:Class="DragDropControl.DDControl"
             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:DragDropControl"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300"
             x:Name="CurrentControl">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <TextBox Name="txtGroupName" Grid.Row="0" Text="{Binding ElementName=CurrentControl, Path=ThisData.GroupName}"/>
    <ListBox Name="lstTitles" Grid.Row="1" ItemsSource="{Binding ElementName=CurrentControl, Path=ThisData.Titles}">
      <ListBox.ItemTemplate>
        <DataTemplate>
          <Label Name="lblTitle" Content="{Binding Title}"/>
        </DataTemplate>
      </ListBox.ItemTemplate>
    </ListBox>
  </Grid>
</UserControl>

DDControl - кодпозади

using DragDropControl.Model;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace DragDropControl
{
  /// <summary>
  /// Interaction logic for UserControl1.xaml
  /// </summary>
  public partial class DDControl : UserControl
  {
    public static readonly DependencyProperty ThisDataProperty = DependencyProperty.Register( "ThisData",
                                                                                              typeof(SimpleDataClass),
                                                                                              typeof(DDControl),
                                                                                              new PropertyMetadata(new SimpleDataClass()));
    public SimpleDataClass ThisData
    {
      get { return (SimpleDataClass)GetValue(ThisDataProperty); }
      set { SetValue(ThisDataProperty, value); }
    }


    public DDControl()
    {
      InitializeComponent();
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
      base.OnMouseMove(e);
      if (e.LeftButton == MouseButtonState.Pressed)
      {
        DataObject data = new DataObject(this.ThisData);

        DragDrop.DoDragDrop(this, data, DragDropEffects.Move);
      }
    }

    protected override void OnGiveFeedback(GiveFeedbackEventArgs e)
    {
      base.OnGiveFeedback(e);
      if (e.Effects.HasFlag(DragDropEffects.Move))
        Mouse.SetCursor(Cursors.Pen);

      e.Handled = true;
    }
  }
}

MainWindow - Xaml

<Window x:Class="DragDropUserControlWithTextBox.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:DragDropUserControlWithTextBox"
        xmlns:ddc="clr-namespace:DragDropControl;assembly=DragDropControl"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
  <Grid>
    <ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
      <StackPanel Name="stkMain" Background="Gray" Orientation="Horizontal" Drop="stkMain_Drop" AllowDrop="true">
        <ItemsControl Name="icColumns" Background="Red">
          <ItemsControl.ItemsPanel>
            <ItemsPanelTemplate>
              <StackPanel Name="stkItemsControlPanel" Orientation="Horizontal"/>
            </ItemsPanelTemplate>
          </ItemsControl.ItemsPanel>
          <ItemsControl.ItemTemplate>
            <DataTemplate>
              <ddc:DDControl Background="{x:Null}" ThisData="{Binding}"/><!-- MouseMove="DDControl_MouseMove" GiveFeedback="DDControl_GiveFeedback"/>-->
            </DataTemplate>
          </ItemsControl.ItemTemplate>
        </ItemsControl>
        <Button Name="btnAddData" Content="Add Data" Click="btnAddData_Click"/>
      </StackPanel>
    </ScrollViewer>
  </Grid>
</Window>

MainWindow - код позади

using DragDropControl.Model;
using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;

namespace DragDropUserControlWithTextBox
{
  /// <summary>
  /// Interaction logic for MainWindow.xaml
  /// </summary>
  public partial class MainWindow : Window
  {
    private ObservableCollection<SimpleDataClass> _data = new ObservableCollection<SimpleDataClass>();

    public MainWindow()
    {
      InitializeComponent();

      CreateTestData();
    }

    private void CreateTestData()
    {
      SimpleDataClass tempSDC1 = new SimpleDataClass();
      tempSDC1.GroupName = "First Item";
      tempSDC1.Titles.Add(new SimpleSubDataClass("Title 1_1"));
      tempSDC1.Titles.Add(new SimpleSubDataClass("Title 1_2"));
      tempSDC1.Titles.Add(new SimpleSubDataClass("Title 1_3"));
      tempSDC1.Titles.Add(new SimpleSubDataClass("Title 1_4"));
      tempSDC1.Titles.Add(new SimpleSubDataClass("Title 1_5"));

      SimpleDataClass tempSDC2 = new SimpleDataClass();
      tempSDC2.GroupName = "Second Item";
      tempSDC2.Titles.Add(new SimpleSubDataClass("Title 2_1"));
      tempSDC2.Titles.Add(new SimpleSubDataClass("Title 2_2"));
      tempSDC2.Titles.Add(new SimpleSubDataClass("Title 2_3"));
      tempSDC2.Titles.Add(new SimpleSubDataClass("Title 2_4"));
      tempSDC2.Titles.Add(new SimpleSubDataClass("Title 2_5"));

      _data.Add(tempSDC1);
      _data.Add(tempSDC2);

      this.icColumns.ItemsSource = _data;
    }

    private void stkMain_Drop(object sender, DragEventArgs e)
    {
      if (e.Handled == false)
      {
        if (e.Data.GetDataPresent(typeof(SimpleDataClass)))
        {
          SimpleDataClass tempData = (SimpleDataClass)e.Data.GetData(typeof(SimpleDataClass));

          _data.Add(tempData);
        }

        e.Effects.HasFlag(DragDropEffects.None);
        Mouse.SetCursor(Cursors.Arrow);
        e.Handled = true;
      }
    }

    private void btnAddData_Click(object sender, RoutedEventArgs e)
    {
      SimpleDataClass tempData = new SimpleDataClass();
      tempData.GroupName = "Amazing Test";
      tempData.Titles.Add(new SimpleSubDataClass("AT_1"));
      tempData.Titles.Add(new SimpleSubDataClass("AT_2"));
      tempData.Titles.Add(new SimpleSubDataClass("AT_3"));
      _data.Add(tempData);
    }
  }
}

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Для перетаскивания создайте Поведение и обработайте события в Поведении, чтобы избежать сценариев замораживания потока пользовательского интерфейса.Проверка по приведенной ниже ссылке будет полезна для вашего сценария.https://www.telerik.com/blogs/adding-drag-and-drop-to-wpf-listboxes-thanks-telerik!

0 голосов
/ 27 сентября 2018

Я переключился на метод, описанный в этом WPF-руководстве при перетаскивании.У него все еще была проблема, когда вы перетаскивали пользовательский элемент управления с текстовым полем на нем (предполагалось бы, что это будет сделано для любого элемента управления, который может быть изменен), когда он создавал бы второй экземпляр перетаскиваемого элемента, но с ним довольно легко работатьвокруг, просто установите для включенного состояния значение false, когда обнаруживается, что элемент управления собирается перетащить, и включите его снова, когда он будет отброшен.Возможно, взломать, но тот, который работает.

...