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

私のメインウィンドウ 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">

何も起こりません、理由はわかりますか?

アプリケーションの任意のウィンドウをメイン ウィンドウにドロップするにはどうすればよいですか?

私がやろうとしていることを示すために ここに画像の説明を入力 、tabitem5とtabitem2がメインウィンドウの外にドラッグされたため、独立したウィンドウになりました。今、プロセスを逆にして、メインウィンドウにドラッグして再びタブにしようとしています

私は完全なコードサンプル、タブからウィンドウ、ウィンドウからタブへの報奨金を与えています.mvvmソリューションも受け入れられます

4

1 に答える 1

8

ドッキングシステムを実装しようとしているようです。既存のドッキング マネージャーを見たことがありますか。

Avalon Dockは、優れたオープン ソースの例です。よく文書化されており、使いやすいです。

独自のものを実装することに決めた場合は、ドラッグしているウィンドウの下にウィンドウがあるかどうかを確認できます。残念ながら、WPF には、Windows 全体で HitTest を行う簡単な方法がありません。これを回避する方法は、いくつかの Win32 呼び出しを行うことです。ここで使用されているコードは、 Ray Burnsによる別の SO スレッドと、 Fredrik Hedbladによる現在のマウス位置を取得するための Win32 呼び出しからのものです。

また、ウィンドウのカスタム タイトル バーを使用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();
    }
}
于 2013-10-31T05:27:00.993 に答える