2013-10-25 22 views
12

thả sự kiện của tôiThả một cửa sổ vào một cửa sổ khác

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 My

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

Không có gì xảy ra, bất kỳ ý tưởng tại sao?

Làm cách nào để thả bất kỳ cửa sổ nào vào ứng dụng của tôi vào cửa sổ chính?

để chứng minh những gì tôi đang cố gắng để làm enter image description here các tabitem5 và tabitem2 bị lôi ra ngoài MainWindow và do đó trở thành cửa sổ độc lập, bây giờ tôi đang cố gắng để đảo ngược quá trình và làm cho họ tab một lần nữa bằng cách kéo chúng vào chính cửa sổ

tôi đang đưa ra bounty cho một mẫu mã đầy đủ, tab để cửa sổ và cửa sổ tab, một giải pháp có thể chấp nhận MVVM là quá

+0

xin vui lòng gửi mã đầy đủ của bạn bao gồm cả mã đó là bắt đầu các hoạt động kéo. –

+0

@HighCore thats những gì tôi đang thiếu sau đó – FPGA

+0

@ HighCore PreviewMouse Handler nên được trên cửa sổ phụ mà tôi muốn kéo? – FPGA

Trả lời

8

có vẻ như bạn đang cố gắng để thực hiện một hệ thống lắp ghép. Bạn đã xem qua các Trình quản lý Docking hiện có chưa.

Avalon Dock là một ví dụ nguồn mở tuyệt vời. Nó cũng được tài liệu và dễ sử dụng.

Nếu bạn quyết tâm thực hiện của riêng mình, bạn có thể thử tìm xem có cửa sổ nào bên dưới cửa sổ bạn đang kéo hay không. Thật không may WPF không có một cách dễ dàng để HitTest trên Windows. Cách này sẽ là thực hiện một số cuộc gọi Win32. Mã được sử dụng là từ một sợi SO khác here, bằng Ray Burns và cuộc gọi Win32 để nhận số mouse position hiện tại, theo số Fredrik Hedblad.

Tôi cũng đã sử dụng WindowStyle="None" và triển khai thanh tiêu đề tùy chỉnh cho cửa sổ để tôi có thể nắm bắt các sự kiện chuột trên cửa sổ.

Tôi không hoàn toàn chắc chắn cách bạn đã triển khai kéo tab để tạo cửa sổ mới nhưng nếu điều đó đang hoạt động, bạn có thể thực hiện các thao tác sau.

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

Main Window XAML (ví dụ)

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

Main Window Mã (ví dụ)

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

chỉ là hoàn hảo, điều này là với người quản lý dock có sẵn họ không hỗ trợ chuyển đổi mục dock sang cửa sổ riêng biệt, tôi muốn xem các mục dock của tôi trong thanh tác vụ và tôi không muốn chúng giảm thiểu khi tôi giảm thiểu ứng dụng, +185, và tôi ước tôi có thể cung cấp cho bạn thêm – FPGA

+0

Điều này xứng đáng với hàng tá phiếu bầu! –

Các vấn đề liên quan