2013-10-25 9 views
12

mio evento di rilascioEliminare una finestra in un'altra finestra

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

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

Non succede nulla, qualche idea del perché?

Come posso rilasciare qualsiasi finestra nella mia applicazione nella finestra principale?

per dimostrare quello che sto cercando di fare enter image description here il tabitem5 e tabitem2 sono stati trascinati fuori dal MainWindow e quindi la diventato finestre indipendenti, ora sto cercando di invertire il processo e le schede rendere nuovamente trascinandoli alla principale finestra

sto dando la bontà per un esempio di codice completo, scheda di finestra e finestra per scheda, una soluzione MVVM è accettabile troppo

+0

si prega di inviare il codice completo, compreso il codice che sta partendo l'operazione di trascinamento. –

+0

@HighCore questo è quello che mi manca allora – FPGA

+0

@HighCore Il gestore di PreviewMouseMove dovrebbe essere nella finestra secondaria che voglio trascinare? – FPGA

risposta

8

sembra che si sta cercando di implementare un sistema di collegamento. Hai dato un'occhiata ai gestori di Dock esistenti.

Avalon Dock è un grande esempio di Open Source. È ben documentato e facile da usare.

Se sei determinato a implementare il tuo, puoi provare a trovare se c'è una Finestra sotto quella che stai trascinando. Sfortunatamente WPF non ha un modo semplice per HitTest su Windows. Il modo per aggirare questo sarebbe fare alcune chiamate Win32. Il codice utilizzato proviene da un'altra stringa SO here, da Ray Burns e una chiamata Win32 per ottenere l'attuale mouse position, per Fredrik Hedblad.

Ho anche utilizzato WindowStyle="None" e implementato una barra del titolo personalizzata per la finestra in modo da poter catturare gli eventi del mouse sulla finestra.

Non sono del tutto sicuro di come è stato implementato il trascinamento della scheda per creare una nuova finestra, ma se funziona è possibile effettuare quanto segue.

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> 

Codice

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

Finestra principale Xaml (esempio)

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

principale finestra di codice (esempio)

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

semplicemente perfetto, il fatto è che con i gestori di dock disponibili non supportano la conversione dell'oggetto dock in una finestra separata, voglio vedere i miei oggetti dock nella barra delle applicazioni e non voglio che minimizzino quando minimizzo l'applicazione, +185, e vorrei poterti dare di più – FPGA

+0

Questo merita una dozzina di voti! –

Problemi correlati