zoukankan      html  css  js  c++  java
  • 用AvalonDock制作WPF多标签浏览器(三)

    昨天遇到了一个Bug,如果在浏览器中打开多个标签,并把其中一个标签拖拽到主窗口的一侧来划分出独立的一个区域,然后在新区域中通过点击加号键添加的新标签内不会被添加上WebBrowser

    说得好绕嘴啊,截张图吧:


    而且没有加上WebBrowser的标签的标题是new content(我们在AvalonDock中给新标签的默认标题)而不是New Tab(客户代码中重新赋的值)。

    OK,问题明了了,是不是新添加的标签的Got_Focus没能够挂到客户代码中的方法上去呢?

    的确是这样,当我们把一个标签(DocumentContent)拖拽到一侧从而划分出一个新区域的时候,AvalonDock会创建一个新的DocumentPane来代表这个新区域。

    我们浏览器中默认的DocumentPane是在XAML中声明的,声明时其NewContentAdded

    事件就挂到了事件响应方法DocumentPane_NewContentAdded上。

    而这个新区域中的DocumentPane是在AvalonDock内部的DocumentFloatingWindow类中创建的,其事件自然没有挂上来。

    知道了这些,解决方案自然就有了。

    DocumentFloatingWindow中添加如下事件:

    public static event EventHandler<NewDocumentPaneAddedByMouseEventArgs> NewDocumentPaneAddedByMouse;

    其中用到的事件参数定义如下:

     public class NewDocumentPaneAddedByMouseEventArgs : EventArgs

        {

            public NewDocumentPaneAddedByMouseEventArgs(DocumentPane addedPane)

            {

                AddedPane = addedPane;

            }

            public DocumentPane AddedPane

            {

                get;

                private set;

            }

        }

    依然尊规范在DocumentFloatingWindow中定义如下方法来触发事件:

    private void OnNewDocumentPaneAddedByMouse(NewDocumentPaneAddedByMouseEventArgs args)

            {

                if (NewDocumentPaneAddedByMouse != null)

                {

                    NewDocumentPaneAddedByMouse(this, args);

                }

            }

    并在DocumentFloatingWindow中的ClonePane方法(鼠标拖拽时创建新DocumentPane的工作就是在这个方法中做的)中调用该方法来触发事件,修改后的ClonePane方法是这样的:

    public override Pane ClonePane()

            {

                DocumentPane paneToAnchor = new DocumentPane();

                OnNewDocumentPaneAddedByMouse(new NewDocumentPaneAddedByMouseEventArgs(paneToAnchor));   

                ResizingPanel.SetEffectiveSize(paneToAnchor, new Size(Width, Height));

               while (HostedPane.Items.Count > 0)

                {

                    paneToAnchor.Items.Add(

                        HostedPane.RemoveContent(0));

                }

                return paneToAnchor;

            }

    我们只关心其中的OnNewDocumentPaneAddedByMouse(new NewDocumentPaneAddedByMouseEventArgs(paneToAnchor));  这一句就OK了。

    好了,现在每当因鼠标拖拽而创建出一个新的DocumentPane时,都有一个事件会被触发,而且其传递的事件参数中还含有对新添加的DocumentPane实例的引用。这样订阅事件的地方(比如说我们的客户代码中)就可以通过该引用来把新添加的DocumentPaneNewContentAdded事件挂到某个方法上了(当然就是我们的DocumentPane_NewContentAdded方法了)。

    接下来修改客户代码吧:

    在浏览器窗口的构造方法中添加下面一句:

    DocumentFloatingWindow.NewDocumentPaneAddedByMouse +=

                    (object sender, NewDocumentPaneAddedByMouseEventArgs e) =>

                    {

                        e.AddedPane.NewContentAdded += DocumentPane_NewContentAdded;

                    };

    用了lambda表达式,有点长,不过的确还只是一句啊。

    这样每个通过鼠标拖拽出来的DocumentPane就和我们在XAML中声明的DocumentPane没什么两样了,它们的NewContentAdded 事件都挂到了DocumentPane_NewContentAdded方法上,这个方法做什么的来着?它做的就是给每一个新标签中置入一个新的WebBrowser

    好了,现在再运行一下,之前的问题不见了。

    另外,如果你在使用Win7的话,把某个新标签拖拽出窗口,右击,选择Floating


    然后就可以把这个拖拽出来的标签Dock到屏幕的一侧了

    那个玻璃化的框框好漂亮啊,呵呵。

    好了,到现在为止我们的多标签浏览器基本就运转起来了。如果您发现其中隐含的Bug或者不妥之处请不吝赐教哈!

    另外,AvalonDock有两套Theme,我们之前的Restyle只修改了DocumentPaneStyles.xaml,要在Win7下看到想要的效果还要对aero.normalcolor.xaml做同样的修改。

    好了,Over and out

     

  • 相关阅读:
    hdu 1199 Color the Ball 离散线段树
    poj 2623 Sequence Median 堆的灵活运用
    hdu 2251 Dungeon Master bfs
    HDU 1166 敌兵布阵 线段树
    UVALive 4426 Blast the Enemy! 计算几何求重心
    UVALive 4425 Another Brick in the Wall 暴力
    UVALive 4423 String LD 暴力
    UVALive 4872 Underground Cables 最小生成树
    UVALive 4870 Roller Coaster 01背包
    UVALive 4869 Profits DP
  • 原文地址:https://www.cnblogs.com/cuipengfei/p/1688510.html
Copyright © 2011-2022 走看看