2013-10-25 3 views
12

Мое падение событиеОставьте окно в другое окно

private void Window_Drop(object sender, DragEventArgs e) 
{ 
    var window = e.Data.GetData(typeof(Window)) as Window; 
    if (window != null) 
    { 
     var tabitem = new TabItem(); 
     tabitem.Content = window.Content; 
     tabcontrol1.Items.Add(tabitem); 
     window.Close(); 
    } 
} 

Мой MainWindow XAML

<Window x:Class="WpfApplication2.MainWindow" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      Title="MainWindow" Height="350" Width="525" Drop="Window_Drop"> 

Ничего не происходит, любая идея, почему?

Как я могу удалить любое окно в моем приложении в основное окно?

, чтобы продемонстрировать то, что я пытаюсь сделать enter image description here в tabitem5 и tabitem2 вытащили за пределы MainWindow и, таким образом, стали независимыми окнами, теперь я пытаюсь изменить процесс и сделать их язычки снова путем перетаскивания их основной окно

я даю награду за полный образец кода, вкладки в окно и окно вкладки, MVVM решение приемлемо слишком

+0

пожалуйста, напишите свой полный код, включая код, который начинает операцию перетаскивания. –

+0

@HighCore thats то, чего я не хватает, то – FPGA

+0

@HighCore PreviewMouseMove обработчик должен быть в дополнительном окне, которое я хочу перетащить? – FPGA

ответ

8

это звучит, как вы пытаетесь внедрить систему стыковки. Вы посмотрели на существующих менеджеров стыковки.

Avalon Dock - отличный пример с открытым исходным кодом. Он хорошо документирован и прост в использовании.

Если вы намерены реализовать свои собственные, вы можете попытаться найти, есть ли окно под тем, которое вы перетаскиваете. К сожалению, WPF не имеет простого способа HitTest через Windows. Путь вокруг этого - сделать некоторые вызовы Win32. Используемый код относится к другому потоку SO here, по Ray Burns и вызову Win32 для получения тока mouse position, по Fredrik Hedblad.

Я также использовал WindowStyle="None" и внедрил настраиваемую строку заголовка для окна, чтобы я мог поймать события мыши в окне.

Я не совсем уверен, как вы применили табуляцию, чтобы создать новое окно, но если это работает, вы можете сделать следующее.

XAML

<Window x:Class="WpfApplication1.DraggedWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Dragged Window" Height="350" Width="525" 
    MouseMove="DraggedWindow_OnMouseMove" MouseDown="DraggedWindow_OnMouseDown" MouseUp="DraggedWindow_OnMouseUp" WindowStyle="None"> 
<Window.Resources> 
    <Style TargetType="HeaderedContentControl"> 
     <Setter Property="HeaderTemplate"> 
      <Setter.Value> 
       <DataTemplate> 
        <Border Background="Gray" Opacity="0.8"> 
         <DockPanel LastChildFill="True"> 
          <Button DockPanel.Dock="Right" Content="X" Width="20" Height="20" Margin="2"/> 
          <TextBlock DockPanel.Dock="Left" Text="{Binding Header}"/> 
         </DockPanel> 
        </Border> 
       </DataTemplate> 
      </Setter.Value> 
     </Setter> 
    </Style> 
</Window.Resources> 
<Grid> 
    <HeaderedContentControl Header="{Binding}" Content="{Binding Content}"/> 
</Grid> 

Код

public partial class DraggedWindow : Window 
{ 
    private readonly MainWindow _mainWindow; 
    private bool _isDropped = false; 

    public DraggedWindow(MainWindow mainWindow) 
    { 
     _mainWindow = mainWindow; 
     InitializeComponent(); 
     DataContext = new TabItem() { Header = "TabItem6", Content = "Content6" }; 
    } 

    const uint GW_HWNDNEXT = 2; 

    [DllImport("User32")] 
    static extern IntPtr GetTopWindow(IntPtr hWnd); 
    [DllImport("User32")] 
    static extern IntPtr GetWindow(IntPtr hWnd, uint wCmd); 
    [DllImport("User32")] 
    [return: MarshalAs(UnmanagedType.Bool)] 
    internal static extern bool GetCursorPos(ref Win32Point pt); 

    [StructLayout(LayoutKind.Sequential)] 
    internal struct Win32Point 
    { 
     public Int32 X; 
     public Int32 Y; 
    }; 

    public static Point GetMousePosition() 
    { 
     Win32Point w32Mouse = new Win32Point(); 
     GetCursorPos(ref w32Mouse); 
     return new Point(w32Mouse.X, w32Mouse.Y); 
    } 

    public Window FindWindowUnderThisAt(Point screenPoint) // WPF units (96dpi), not device units 
    { 
     return (
      from win in SortWindowsTopToBottom(Application.Current.Windows.OfType<Window>()) 
      where new Rect(win.Left, win.Top, win.Width, win.Height).Contains(screenPoint) 
      && !Equals(win, this) 
      select win 
     ).FirstOrDefault(); 
    } 

    public IEnumerable<Window> SortWindowsTopToBottom(IEnumerable<Window> unsorted) 
    { 
     var byHandle = unsorted.ToDictionary(win => 
      ((HwndSource)PresentationSource.FromVisual(win)).Handle); 

     for (IntPtr hWnd = GetTopWindow(IntPtr.Zero); hWnd != IntPtr.Zero; hWnd = GetWindow(hWnd, GW_HWNDNEXT)) 
     { 
      if (byHandle.ContainsKey(hWnd)) 
       yield return byHandle[hWnd]; 
     } 
    } 

    private void DraggedWindow_OnMouseMove(object sender, MouseEventArgs e) 
    { 
     if (e.LeftButton == MouseButtonState.Pressed) 
     { 
      this.DragMove(); 
     } 

     var absoluteScreenPos = GetMousePosition(); 
     var windowUnder = FindWindowUnderThisAt(absoluteScreenPos); 
     if (windowUnder != null && windowUnder.Equals(_mainWindow)) 
     { 
      if (_isDropped) 
      { 
       // Your code here 
       var tabitem = new TabItem(); 
       tabitem.Content = (DataContext as TabItem).Content; 
       tabitem.Header = (DataContext as TabItem).Header; 
       _mainWindow.TabControl1.Items.Add(tabitem); 
       this.Close(); 
      } 
     } 
    } 

    private void DraggedWindow_OnMouseDown(object sender, MouseButtonEventArgs e) 
    { 
     _isDropped = false; 
    } 

    private void DraggedWindow_OnMouseUp(object sender, MouseButtonEventArgs e) 
    { 
     _isDropped = true; 
    } 
} 

Главное окно Xaml (пример)

<Window x:Class="WpfApplication1.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Window1" Height="350" Width="525"> 
<Grid> 
    <TabControl Name="TabControl1"> 
     <TabItem Header="TabItem1">Content1</TabItem> 
     <TabItem Header="TabItem2">Content2</TabItem> 
     <TabItem Header="TabItem3">Content3</TabItem> 
     <TabItem Header="TabItem4">Content4</TabItem> 
     <TabItem Header="TabItem5">Content5</TabItem> 
    </TabControl> 
</Grid> 

Главное окно кода (пример)

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     new DraggedWindow(this).Show(); 
    } 
} 
+1

просто отлично, дело в том, что с доступными диспетчерами док-станции они не поддерживают преобразование элемента док-станции в отдельное окно, я хочу видеть мои элементы док-станции в панели задач, и я не хочу, чтобы они минимизировали, когда я минимизирую приложение, +185, и я хочу, чтобы я мог дать вам больше – FPGA

+0

Это заслуживает дюжины голосов! –

Смежные вопросы