При перетаскивании в wpf фон Adorner становится пустым - PullRequest
0 голосов
/ 25 сентября 2018

Я использовал Adorner при перетаскивании.Иногда при перетаскивании элемента списка цвет фона становится нулевым, виден только контент.Это происходит только при быстром перетаскивании элемента списка.Если выбран элемент списка, то виден только цвет фона.Пожалуйста, предоставьте любое предложение, чтобы решить эту проблему.

Adorner

    public class DragAdorner : Adorner
    {
        public DragAdorner(UIElement owner) : base(owner) { }

        public DragAdorner(UIElement owner, UIElement adornElement, bool useVisualBrush, double opacity)
            : base(owner)
        {
            _owner = owner;
            VisualBrush _brush = new VisualBrush
            {
                Opacity = opacity,                
                Visual = adornElement,                               
            };

            DropShadowEffect dropShadowEffect = new DropShadowEffect
            {
                Color = Colors.Black,
                BlurRadius = 0,
                Opacity = opacity
            };

            Rectangle r = new Rectangle
            {                
                RadiusX = 3,
                RadiusY = 3,
                Fill = Brushes.LightSkyBlue,
                Width = ((FrameworkElement)adornElement).ActualWidth,
                Height = ((FrameworkElement)adornElement).ActualHeight
            };


            XCenter = adornElement.DesiredSize.Width / 2;
            YCenter = adornElement.DesiredSize.Height / 2;

            _child = r;
        }

        private void UpdatePosition()
        {
            AdornerLayer adorner = (AdornerLayer)Parent;
            if (adorner != null)
            {
                adorner.Update(AdornedElement);
            }
        }

        #region Overrides

        protected override Visual GetVisualChild(int index)
        {
            return _child;
        }
        protected override int VisualChildrenCount
        {
            get
            {
                return 1;
            }
        }
        protected override Size MeasureOverride(Size finalSize)
        {
            _child.Measure(finalSize);
            return _child.DesiredSize;
        }
        protected override Size ArrangeOverride(Size finalSize)
        {

            _child.Arrange(new Rect(_child.DesiredSize));
            return finalSize;
        }
        public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
        {
            GeneralTransformGroup result = new GeneralTransformGroup();

            result.Children.Add(base.GetDesiredTransform(transform));
            result.Children.Add(new TranslateTransform(_leftOffset, _topOffset));
            return result;
        }

        #endregion

        #region Field & Properties

        public double scale = 1.0;
        protected UIElement _child;
        protected VisualBrush _brush;
        protected UIElement _owner;
        protected double XCenter;
        protected double YCenter;
        private double _leftOffset;
        public double LeftOffset
        {
            get { return _leftOffset; }
            set
            {
                _leftOffset = value;
                UpdatePosition();
            }
        }
        private double _topOffset;
        public double TopOffset
        {
            get { return _topOffset; }
            set
            {
                _topOffset = value;

                UpdatePosition();
            }
        }

        #endregion
    }

Поведение перетаскивания

    public class DragDropBehavior : Behavior<UIElement>
    {
        #region Fields

        // Using a DependencyProperty as the backing store for CommandParameter.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty CommandParameterProperty =
            DependencyProperty.Register("CommandParameter", typeof(object), typeof(DragDropBehavior));
        // Using a DependencyProperty as the backing store for IsSource.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsSourceProperty =
            DependencyProperty.RegisterAttached("IsSource", typeof(bool), typeof(DragDropBehavior), new PropertyMetadata(true));
        public ListBox list;
        internal DragAdorner _adorner;
        internal AdornerLayer _layer;
        internal ListBoxItem draggedItem = null;
        internal Win32Point w32Mouse = new Win32Point();
        private static bool IsDragging = false;
        private bool _dragHasLeftScope;
        private Point startingPoint;

        #endregion

        #region Properties

        public object CommandParameter
        {
            get { return (object)GetValue(CommandParameterProperty); }
            set { SetValue(CommandParameterProperty, value); }
        }
        public FrameworkElement DragScope { get; set; }
        private static GroupModel dataObject { get; set; }

        #endregion

        #region Methods

        public static bool GetIsSource(DependencyObject obj)
        {
            return (bool)obj.GetValue(IsSourceProperty);
        }
        public static void SetIsSource(DependencyObject obj, bool value)
        {
            obj.SetValue(IsSourceProperty, value);
        }
        [DllImport("user32.dll")]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool GetCursorPos(ref Win32Point pt);
        internal void Window_DragOver(object sender, DragEventArgs args)
        {
            if (_adorner == null) return;
            _adorner.LeftOffset = args.GetPosition(DragScope).X;
            _adorner.TopOffset = args.GetPosition(DragScope).Y;
        }
        protected override void OnAttached()
        {
            this.AssociatedObject.Drop += (sender, e) =>
            {
                var source = ((ListBox)sender).GetValue(IsSourceProperty);

                if (sender is ListBox && !(bool)source)
                {
                    ListBox listBox = (sender as ListBox);
                    DataObject item = (((DragEventArgs)e).Data) as DataObject;

                    if (item != null)
                    {
                        var listItem = item.GetData(typeof(GroupModel));
                        var detailsItems = listItem as GroupModel;
                        (listBox.DataContext as PanelModel).DetailsCollection.Add(new GroupModel { Key = detailsItems.Key, Values = detailsItems.Values });
                    }

                    IsDragging = false;
                    dataObject = null;
                    e.Handled = true;
                }
            };
            this.AssociatedObject.PreviewMouseLeftButtonDown += (sender, e) =>
            {
                var listBoxItem = VisualHelper.FindParentOfType(e.OriginalSource as DependencyObject, typeof(ListBoxItem)) as ListBoxItem;
                if (listBoxItem != null)
                {
                    startingPoint = e.GetPosition(sender as UIElement);
                    Expander parent = (sender as ListBox).Parent as Expander;

                    if (parent != null)
                    {
                        GroupModel details = new GroupModel();
                        details.Key = (parent.DataContext as GroupModel).Key;
                        ObservableCollection<ValueModel> values = new ObservableCollection<ValueModel>();
                        values.Add(listBoxItem.DataContext as ValueModel);
                        details.Values = values;
                        dataObject = details;
                        draggedItem = VisualHelper.FindParentOfType(e.OriginalSource as DependencyObject, typeof(ListBoxItem)) as ListBoxItem;
                    }
                }
                else
                {
                    dataObject = null;
                    IsDragging = false;
                }
            };
            this.AssociatedObject.PreviewMouseMove += (sender, e) =>
            {
                if (e.LeftButton == MouseButtonState.Pressed && dataObject != null && !IsDragging)
                {
                    var currentPoint = e.GetPosition(sender as UIElement);
                    if (Math.Abs(currentPoint.X - startingPoint.X) > 10 || (Math.Abs(currentPoint.Y - startingPoint.Y) > 10))
                    {
                        IsDragging = true;

                        if (draggedItem != null && CommandParameter != null)
                        {
                            StartDragInProcAdorner(e);
                        }
                    }
                }

            };
            this.AssociatedObject.PreviewMouseLeftButtonUp += (sender, e) =>
            {
                dataObject = null;
                IsDragging = false;
            };
        }
        private void StartDragInProcAdorner(MouseEventArgs e)
        {

            DragScope = (CommandParameter as UserControl).Content as FrameworkElement;

            bool previousDrop = DragScope.AllowDrop;
            DragScope.AllowDrop = true;
            try
            {
                DragEventHandler draghandler = Window_DragOver;
                DragScope.PreviewDragOver += draghandler;

                FrameworkElement dr = draggedItem as FrameworkElement;

                if (dr == null)
                    return;
                _adorner = new DragAdorner(DragScope, dr, true, 0.7);
                _layer = AdornerLayer.GetAdornerLayer(DragScope);
                _layer.Add(_adorner);


                IsDragging = true;
                _dragHasLeftScope = false;

                DataObject data = new DataObject(dataObject);
                DragDropEffects de = DragDrop.DoDragDrop(e.Source as ListBox, data, DragDropEffects.Move);

                DragScope.AllowDrop = previousDrop;
                AdornerLayer.GetAdornerLayer(DragScope).Remove(_adorner);
                _adorner = null;

                DragScope.PreviewDragOver -= draghandler;

                IsDragging = false;
            }
            catch
            {
                DragScope.AllowDrop = previousDrop;
                AdornerLayer.GetAdornerLayer(DragScope).Remove(_adorner);
                _adorner = null;
                IsDragging = false;
            }
        }

        #endregion

        /// <summary>
        /// Defines the <see cref="Win32Point" />
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        internal struct Win32Point
        {
            #region Fields

            public Int32 X;
            public Int32 Y;

            #endregion
        }
    }
...