У нас есть список, который мы используем для отображения столбцов в сетке. Пользователь может проверить столбцы, которые он хочет отобразить, и перетащить столбец, чтобы изменить порядок столбцов, отображаемых в сетке. Мы реализуем перетаскивание с пользовательским визуалом и использовали эту статью и эту статью для справки. Вторая статья относится к блогу Майкрософт от Jam ie Rodriguez, в котором есть три архивные статьи: Drag and Drop End to End , Drag and Drop Part 2 и Перетаскивание Часть 3 .
Выбор столбца - это собственный элемент управления, который можно прикрепить к заголовку сетки (xaml и код, показанный ниже). Иногда событие drop вызывается, иногда это не так. Что приводит к тому, что событие drop не вызывается? Другая наша проблема - когда происходит сбой, пользовательский интерфейс перестает отвечать, что может вызвать это? Если мы отключим, как показано ниже, пользовательский визуал, то все будет работать так, как должно:
if ( e.LeftButton == MouseButtonState.Pressed )
{
Trace ( "Chooser_PreviewMouseMove enter" );
var listBoxItem = FindVisualParent<ListBoxItem> ( ( ( DependencyObject ) e.OriginalSource ) );
if ( listBoxItem != null )
{
var dragItem = listBoxItem.DataContext as IColumnSetting;
if ( dragItem != null )
{
//CreateDragDropWindow ( dragItem );
DragDrop.DoDragDrop ( listBoxItem, listBoxItem.DataContext, DragDropEffects.Move );
//CloseDragDropWindow ();
}
}
}
Trace ( "Chooser_PreviewMouseMove exit" );
У нас есть настройка столбца:
public interface IColumnSetting
{
public string Header
{ get; set; }
}
public class ColumnSetting : IColumnSetting
{
public string Header
{ get; set; }
}
, который используется средством выбора столбцов , Затем у нас есть xaml и код для пользовательского элемента управления:
<UserControl
x:Name="root"
x:Class="ColumnApp.ColumnChooser"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation" >
<Grid>
<ListBox
x:Name="Chooser"
BorderThickness="0"
ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=UserControl}, Mode=TwoWay,
Path=ColumnSettings}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox
Content="{Binding Header, Mode=OneWay}"
IsChecked="{Binding IsVisible, Mode=TwoWay}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
и код выбора столбца позади:
public partial class ColumnChooser : UserControl
{
#region Mouse Handling
[StructLayout ( LayoutKind.Sequential )]
private struct Win32Point
{
public Int32 X;
public Int32 Y;
};
[DllImport ( "user32.dll" )]
private static extern bool GetCursorPos ( ref Win32Point pt );
public Point GetMousePosition ()
{
Win32Point mouse = new Win32Point ();
GetCursorPos ( ref mouse );
return new Point () { X = ( double ) mouse.X, Y = (double) mouse.Y };
}
#endregion
#region
public ColumnChooser ()
{
try
{
InitializeComponent ();
Chooser.PreviewMouseMove += Chooser_PreviewMouseMove;
var style = new Style ( typeof ( ListBoxItem ) );
style.Setters.Add ( new Setter ( ListBoxItem.AllowDropProperty, true ) );
style.Setters.Add (
new EventSetter (
ListBoxItem.DropEvent,
new DragEventHandler ( Chooser_Drop ) ) );
style.Setters.Add (
new EventSetter (
ListBoxItem.GiveFeedbackEvent,
new GiveFeedbackEventHandler ( Chooser_GiveFeedback ) ) );
Chooser.ItemContainerStyle = style;
}
catch ( Exception ex )
{
Trace ( "FAILED to create column chooser" );
}
}
#endregion
#region Properties
#endregion
#region Dependency Properties
public ObservableCollection<IColumnSetting> ColumnSettings
{
get { return ( ObservableCollection<IColumnSetting> ) GetValue ( ColumnSettingsProperty ); }
set
{
SetValue ( ColumnSettingsProperty, value );
}
}
public static readonly DependencyProperty ColumnSettingsProperty =
DependencyProperty.Register ( "ColumnSettings", typeof ( ObservableCollection<IColumnSetting> ), typeof ( ColumnChooser ),
new PropertyMetadata ( null ) );
static void OnColumnSettingsChanged ( DependencyObject obj, DependencyPropertyChangedEventArgs e )
{
var model = obj as ColumnChooser;
if ( model == null )
return;
try
{
var columnSettings = model.ColumnSettings;
if ( columnSettings == null || columnSettings.Count == 0 )
{
int i = 0;
i++;
}
//model.Chooser.ItemsSource = columnSettings;
}
catch ( Exception ex )
{
LogProvider.Logger.LogException ( "Error OnCurrentGageChanged", ex );
}
}
#endregion
#region Support Methods
private T FindVisualParent<T> ( DependencyObject child )
where T : DependencyObject
{
var parentObject = VisualTreeHelper.GetParent ( child );
if ( parentObject == null )
return null;
T parent = parentObject as T;
if ( parent != null )
return parent;
return FindVisualParent<T> ( parentObject );
}
#endregion
#region Drap And Drop Handlers
Size DragSz
{ get; set; }
Window DragDropWindow
{ get; set; }
static Point PointToPixel ( Point p )
{
var t = PresentationSource.FromVisual ( Application.Current.MainWindow ).CompositionTarget.TransformFromDevice;
return t.Transform ( p );
}
public FrameworkElement CreateDragVisual ( IColumnSetting columnSetting )
{
if ( columnSetting == null )
throw new ArgumentNullException ( "columnSetting requred" );
var stackPanel = new StackPanel ();
if ( stackPanel == null )
throw new NullReferenceException ( "FAILED to create stack panel" );
var textBlock = new ThemeTextBlock ();
if ( textBlock == null )
throw new NullReferenceException ( "FAILED to create text block" );
textBlock.Text = columnSetting.Header;
stackPanel.Children.Add ( textBlock );
return stackPanel;
}
private void CreateDragDropWindow ( IColumnSetting columnSetting )
{
Trace ( "CreateDragDropWindow enter" );
CloseDragDropWindow ();
DragDropWindow = new Window ();
if ( DragDropWindow == null )
throw new NullReferenceException ( "FAILED to create DragDropWindow" );
DragDropWindow.WindowStyle = WindowStyle.None;
DragDropWindow.AllowsTransparency = true;
DragDropWindow.AllowDrop = false;
DragDropWindow.Background = null;
DragDropWindow.IsHitTestVisible = false;
DragDropWindow.SizeToContent = SizeToContent.WidthAndHeight;
DragDropWindow.Topmost = true;
DragDropWindow.ShowInTaskbar = false;
var dragElement = CreateDragVisual ( columnSetting );
dragElement.Measure ( new Size ( double.PositiveInfinity, double.PositiveInfinity ) );
dragElement.Arrange ( new Rect ( 0, 0, 150, 15 ) );
DragSz = new Size ( dragElement.RenderSize.Width, dragElement.RenderSize.Height );
if ( DragSz == null )
throw new NullReferenceException ( "FAILED to create DragSz" );
this.DragDropWindow.Content = dragElement;
var position = GetMousePosition ();
var cursorPt = PointToPixel ( position );
DragDropWindow.Left = cursorPt.X - ( DragSz.Width / 4 );
DragDropWindow.Top = cursorPt.Y - ( DragSz.Height / 2 );
Trace ( "CreateDragDropWindow DragDropWindow.Left: " + DragDropWindow.Left + " DragDropWindow.Top: " + DragDropWindow.Top );
Trace ( "CreateDragDropWindow cursorPt X: " + cursorPt.X + " cursorPt.Y: " + cursorPt.Y );
DragDropWindow.Show ();
Trace ( "CreateDragDropWindow exit" );
}
private void CloseDragDropWindow ()
{
if ( DragDropWindow == null )
return;
Trace ( "CloseDragDropWindow enter" );
DragDropWindow.Close ();
DragDropWindow = null;
Trace ( "CloseDragDropWindow exit" );
}
public Rect GetControlPosition ( FrameworkElement element )
{
var absolutePos = element.PointToScreen ( new System.Windows.Point ( 0, 0 ) );
return new Rect ( absolutePos.X, absolutePos.Y, element.ActualWidth, element.ActualHeight );
}
private void Chooser_PreviewMouseMove ( object sender, MouseEventArgs e )
{
var lb = sender as ListBox;
if ( lb == null )
return;
if ( e.LeftButton == MouseButtonState.Pressed )
{
Trace ( "Chooser_PreviewMouseMove enter" );
var listBoxItem = FindVisualParent<ListBoxItem> ( ( ( DependencyObject ) e.OriginalSource ) );
if ( listBoxItem != null )
{
var dragItem = listBoxItem.DataContext as IColumnSetting;
if ( dragItem != null )
{
CreateDragDropWindow ( dragItem );
DragDrop.DoDragDrop ( listBoxItem, listBoxItem.DataContext, DragDropEffects.Move );
CloseDragDropWindow ();
}
}
Trace ( "Chooser_PreviewMouseMove exit" );
}
}
private void Chooser_GiveFeedback ( object sender, GiveFeedbackEventArgs e )
{
Trace ( "Chooser_GiveFeedback enter" );
if ( DragDropWindow == null )
return;
var position = GetMousePosition ();
var cursorPt = PointToPixel ( position );
Trace ( "Chooser_GiveFeedback Move DragDropWindow" );
Trace ( "Chooser_GiveFeedback cursorPt X: " + cursorPt.X + " cursorPt.Y: " + cursorPt.Y );
DragDropWindow.Left = cursorPt.X - ( DragSz.Width / 4 );
DragDropWindow.Top = cursorPt.Y - ( DragSz.Height / 2 );
e.Handled = true;
Trace ( "Chooser_GiveFeedback DragDropWindow.Left: " + DragDropWindow.Left + " DragDropWindow.Top: " + DragDropWindow.Top );
Trace ( "Chooser_GiveFeedback Moved DragDropWindow" );
Trace ( "Chooser_GiveFeedback exit" );
}
private void Chooser_Drop ( object sender, DragEventArgs e )
{
Trace ( "Chooser_Drop enter" );
var listBoxItem = sender as ListBoxItem;
if ( listBoxItem == null )
return;
var item = e.Data.GetData ( typeof ( Gt.BaseDefs.ViewSettings.ColumnSetting ) );
if ( item != null )
{
Trace ( "Chooser_Drop moving column" );
var dragItem = item as IColumnSetting;
var dropItem = listBoxItem.DataContext as IColumnSetting;
int dragIndex = ColumnSettings.IndexOf ( dragItem );
int dropIndex = ColumnSettings.IndexOf ( dropItem );
Move ( dragItem, dragIndex, dropIndex );
Trace ( "Chooser_Drop moved column" );
}
Trace ( "Chooser_Drop exit" );
}
private void Move ( IColumnSetting dragItem, int dragIndex, int dropIndex )
{
if ( dragIndex < dropIndex )
{
ColumnSettings.Insert ( dropIndex + 1, dragItem );
ColumnSettings.RemoveAt ( dragIndex );
}
else
{
if ( dragIndex < ColumnSettings.Count + 1 )
{
ColumnSettings.RemoveAt ( dragIndex );
ColumnSettings.Insert ( dropIndex, dragItem );
}
}
}
#endregion
#region ITrace
public void Trace ( string msg )
{
Debug.WriteLine ( msg );
}
#endregion
}