您当前的位置: 首页 > 

寒冰屋

暂无认证

  • 0浏览

    0关注

    2286博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

WPF窗口允许通过拖放进行切换

寒冰屋 发布时间:2019-12-21 14:55:33 ,浏览量:0

目录

介绍

背景

使用代码

TabWindow库的细分

带有关闭按钮的自定义TabItem

派生的TabControl支持自定义选项卡之间的拖放

允许将一个窗口切换到另一个窗口的TabWindow

总结

  • 下载源代码35 KB
介绍

本文介绍了一个称为TabWindow的Shell窗口,它嵌入了TabControl,允许通过拖放将选项卡项分离到一个新窗口。它还允许通过拖放将浮动窗口选项卡固定到窗口中。

背景

您能想象WPF窗口的行为类似于Chrome或Internet Explorer浏览器吗?在运行时,可以通过拖放将一个窗口选项卡移动到另一个窗口中。选项卡可以重新排序,单个选项卡可以关闭。TabWindow支持这些功能。但是,它不仅仅是Chrome等现代浏览器的复制品。有一些主要区别。例如,当TabWindow中选项卡仅剩一项时,选项卡页头就会消失。在GUI中,空间是一项额外的功能,如您所知。同样,当您将一个窗口选项卡移动到另一个窗口时,也可以将其拖到标题栏,而不是由Chrome浏览器拖到选项卡标题的位置。TabWindow,但是,不是一个docking控制。已经有许多商业和开源docking控件可用。TabWindow派生自WPF Window 类,因此所有窗口特性都由开发人员公开。

使用代码

在您的代码中使用TabWindow很简单。在将对TabWindow库的引用添加到您的项目后,首先将TabWindow实例化为常规WPF窗口的引用,然后通过传递将成为TabWindow实例内容的Control实例来调用AddTabItem方法。因此,构建您自己的漂亮用户控件,然后将其传递给TabWindow。

TabWindow.TabWindow tabWin = new TabWindow.TabWindow();
TextBox tb = new TextBox();
tb.Text = "Test Demo";
tabWin.AddTabItem(tb.Text, tb);
tabWin.Show();

根据您的需要,创建尽可能多的TabWindow,然后通过将一个窗口拖到另一个窗口上来开始选项卡窗口。当一个窗口被拖动进入固定TabWindow对象的边界时,将出现一个选项卡放置目标图像。继续拖动,直到鼠标指针悬停在选项卡放置图像上方,然后放开鼠标。拖动的窗口消失,固定的窗口将添加一个新选项卡,其中包含拖动的窗口的内容。

1、两个独立悬浮的TabWindows。

2、将“Test 0”窗口拖到“Test Demo”窗口上。

3、选项卡区域在“测试演示”窗口中突出显示。释放按下的鼠标按钮,然后将“Test 0”窗口切换到“Test Demo”窗口。

为了将选项卡分离到新窗口,请按住选项卡标题并将其拖出现有窗口,或双击选项卡标题。它将创建一个独立的窗口。

TabWindow库的细分

库中主要包括三个部分。每个部分负责其自身的功能。

  • 使用关闭按钮的自定义TabItem
  • 派生自支持自定义TabItem拖放的TabControl
  • 允许将一个窗口切换到另一个窗口的TabWindow 
带有关闭按钮的自定义TabItem

根据Internet上的快速搜索,有多种方法可以完成此任务。我采用了一种方法来创建一个衍生自TabItem的自定义控件。为了在选项卡标题上绘制[x]标记,控件模板样式在XAML中声明。最初,我想到了在选择选项卡时使用图像文件显示[x]标记,但最终使用System.Windows.Shapes.Path对象绘制x形状。这是在Generic.xaml中定义[x]按钮的方式。


  
    
      
        
          
            
          
          
            
          
        
      
    
  
  
    ...
  

如下所示,此关闭按钮样式将应用于选项卡标题模板。DockPanel由停靠在最右侧的[X]和标头ContentPresenter组成。[x]按钮的默认可见性被隐藏。选择选项卡后,它变为可见。用于Trigger显示或隐藏[x]按钮。


...
  
    
      
        
          
            
              
              
            
          
        
      ...
      
    
   

现在我们需要进行一些操作。我希望在单击[x]按钮时将选项卡项删除。双击选项卡标题时,我也想引发一个事件。此双击通知将由TabWindow使用,在那里它将生成一个新 TabWindow并将内容从单击的选项卡项移动到新窗口。基本上,这等效于将选项卡拖出到新窗口,因此双击选项卡标题可创建一个新TabWindow实例,并删除双击的选项卡项。

public override void OnApplyTemplate()
{
  base.OnApplyTemplate();
  Button closeButton = base.GetTemplateChild("tabItemCloseButton") as Button;
  if (closeButton != null)
    closeButton.Click += new System.Windows.RoutedEventHandler(closeButton_Click);
  Grid headerGrid = base.GetTemplateChild("gridHeader") as Grid;
  if (headerGrid != null)
    headerGrid.MouseLeftButtonDown += 
               new MouseButtonEventHandler(headerGrid_MouseLeftButtonDown);
}

void closeButton_Click(object sender, System.Windows.RoutedEventArgs e)
{
  var tabCtrl = this.Parent as TabControl;
  if (tabCtrl != null)
    tabCtrl.Items.Remove(this);
}

void headerGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
  if (e.ClickCount == 2)
    this.RaiseEvent(new RoutedEventArgs(TabHeaderDoubleClickEvent, this));
}
派生的TabControl支持自定义选项卡之间的拖放

网上有很多拖放教程,因此我将不详细介绍通过拖放对选项卡进行重新排序。但是,将选项卡拖出以创建新窗口不是典型的拖放操作。.NET Framework提供了在拖动鼠标指针期间连续引发的QueryCotinueDrag事件。拖动的鼠标位置保持选中状态,当它离开选项卡控件边界时,它会创建一个新的TabWindow。一旦新的TabWindow被创建,新窗口的Left和Top属性通过处理QueryContinueDrag事件得到更新。当放置操作发生时,此事件还提供信号。由于e.KeyStates被设定为DragDropKeyStates.None,是时候从选项卡控件中删除选项卡项。

void DragSupportTabControl_QueryContinueDrag(object sender, QueryContinueDragEventArgs e)
{
  if (e.KeyStates == DragDropKeyStates.LeftMouseButton)
  {
    Win32Helper.Win32Point p = new Win32Helper.Win32Point();
    if (Win32Helper.GetCursorPos(ref p))
    {
      Point _tabPos = this.PointToScreen(new Point(0, 0));
      if (!((p.X >= _tabPos.X && p.X = _tabPos.Y && p.Y  0; i--)
      {
        System.Windows.Controls.TabItem item = items[i - 1] as 
                                        System.Windows.Controls.TabItem;
        if (item != null)
          ((ITabWindow)dragWin).RemoveTabItem(item);
      }
    }
    targetWin.OnDrageLeave();
  }
  if (_dragEnteredWindows.Count > 0 && ((ITabWindow)dragWin).TabItems.Count == 0)
  {
    ((Window)dragWin).Close();
  }
  _dragEnteredWindows.Clear();
}
总结

TabWindow库在复合应用程序中非常有用,在复合应用程序中,模块可以直接加载到TabWindow实例中。然后,将如何将窗口动态合并到选项卡的决定权留给用户。TabWindow的亮点是:

  • 允许对选项卡项进行重新排序
  • 允许关闭选项卡项
  • 当窗口中仅剩一个选项卡项时,选项卡标题将不可见
  • 可以将选项卡项拖出到新窗口
  • 双击选项卡标题会创建一个新窗口
  • 可以通过标题栏拖动一个窗口并将其放在另一个窗口上。源窗口的内容成为目标窗口的新选项卡项。
关注
打赏
1665926880
查看更多评论
立即登录/注册

微信扫码登录

0.1338s