2013-10-25 14 views
12

Moje zdarzenie dropUpuść okno do innego okna

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

Moja 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"> 

Nic się nie dzieje, jakiś pomysł dlaczego?

Jak mogę usunąć dowolne okno z mojej aplikacji do mojego głównego okna?

wykazać co próbuję zrobić enter image description here się tabitem5 i tabitem2 zostały przeciągnięty poza MainWindow i tym samym stało się niezależne okna, teraz staram się odwrócić proces i uczynić je zakładki ponownie przeciągając je do głównego okno

daję nagrodę dla pełnej próbki kodu, karty do okna i okna na karcie rozwiązanie MVVM jest akceptowalne zbyt

+0

proszę umieszczać swój pełny kod wraz z numerem, który zaczyna operację przeciągania. –

+0

@HighCore to, czego mi brakuje, to – FPGA

+0

@HighCore PreviewMouseMove handler powinien być w oknie podrzędnym, które chcę przeciągnąć? – FPGA

Odpowiedz

8

brzmi jak próbujesz wprowadzić system dokowania. Czy spojrzałeś na obecnych kierowników dokowania?

Avalon Dock to świetny przykład Open Source. Jest dobrze udokumentowany i łatwy w użyciu.

Jeśli chcesz wdrożyć własne, możesz spróbować sprawdzić, czy pod tym, co przeciągasz znajduje się okno. Niestety, WPF nie ma łatwego sposobu na trafienie HitTest przez Windows. Sposób obejścia tego spowoduje wykonanie niektórych wywołań Win32. Używany kod pochodzi z innego wątku SO here, przez Ray Burns i wywołania Win32 dla uzyskania bieżącego mouse position, przez Fredrik Hedblad.

Użyłem również WindowStyle="None" i zaimplementowałem niestandardowy pasek tytułu okna, dzięki czemu mogę uchwycić zdarzenia myszy w oknie.

Nie jestem do końca pewien, w jaki sposób zaimplementowano przeciąganie karty w celu utworzenia nowego okna, ale jeśli to działa, można wykonać następujące czynności.

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> 

Kod

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

Okno główne Xaml (przykład)

<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> 

główny kod okno (przykład)

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

Po prostu idealne, chodzi o dostępne menedżery dokowania, które nie obsługują przekształcania elementu dokowania w osobne okno, chcę widzieć moje elementy doków na pasku zadań i nie chcę, aby były minimalizowane, gdy zminimalizuję aplikację, +185, i chciałbym móc dać ci więcej – FPGA

+0

To zasługuje na kilkanaście głosów! –

Powiązane problemy