wpf 移除 AvalonDock 坞站并关闭按钮

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11987893/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-13 04:59:38  来源:igfitidea点击:

Remove AvalonDock dock and close buttons

wpfavalondock

提问by Lews Therin

I would like to remove them as this is causing me lots of problems. If there is a way to solve it I will be glad to try it. First few minutes of using it I have gotten like 3 different exceptions and I can't figure out how to remove those damn options.

我想删除它们,因为这给我带来了很多问题。如果有办法解决它,我会很乐意尝试。使用它的前几分钟我得到了 3 个不同的例外,我不知道如何删除那些该死的选项。

Pinning and unpinning and pinning, throws an InvalidOperationException because the Operation is not valid due to the current state of the object.

固定和取消固定和固定会引发 InvalidOperationException,因为由于对象的当前状态,操作无效。

Sometimes pinning and unpinning will open a dialog box and ask me for a file, I don't want that to happen but it is happening and it throws an exception.

有时固定和取消固定会打开一个对话框并要求我提供一个文件,我不希望这种情况发生,但它正在发生并引发异常。

I accidentally click the close button and I cannot get the window back. It is really frustrating. I am sure other avalondock users have come across this.

我不小心点击了关闭按钮,无法恢复窗口。这真的很令人沮丧。我相信其他 avalondock 用户也遇到过这个问题。

And as I don't want to waste too much time, I am going to ask right here. How did you get around this exceptions or remove those buttons? Thanks.

因为我不想浪费太多时间,所以我要在这里问。您是如何解决此异常或删除这些按钮的?谢谢。

采纳答案by Damascus

I had exactly the same problem as yours. Not willing to remove the icons from the actual UI, I just disabled them with event handlers

我和你的问题完全一样。不愿意从实际用户界面中删除图标,我只是用事件处理程序禁用它们

Here is how I worked:

这是我的工作方式:

To remove those Hide and AutoHide commands:

要删除这些隐藏和自动隐藏命令:

I added the following handler:

我添加了以下处理程序:

CommandManager.AddPreviewExecutedHandler(this, new ExecutedRoutedEventHandler(this.ContentClosing))

This is what ContentClosinglooks like:

ContentClosing看起来像:

/// <summary>
/// Handler called when user clicked on one of the three buttons in a DockablePane
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ContentClosing(object sender, ExecutedRoutedEventArgs e)
{
    if (e.Command == ApplicationCommands.Close || e.Command == DockablePaneCommands.Close)
    {
        e.Handled = true;
        DockManager source = sender as DockManager;
        if (source.ActiveContent != null)
        {
            source.ActiveContent.Close();
        }
    }
    else if (e.Command == DockablePaneCommands.Hide || e.Command == DockablePaneCommands.ToggleAutoHide)
    {
        e.Handled = true;

} }

} }

This handler was here to actually close the right content. Fore some reason, sometimes AvalonDockwill close another content because it has the focus (clicking on the cross won't give focus to your content, and thus it will close the currently focused content...) As you can see, I just override the events and close manually my components

这个处理程序在这里实际上关闭了正确的内容。由于某种原因,有时AvalonDock会关闭另一个内容,因为它具有焦点(单击十字不会将焦点放在您的内容上,因此它将关闭当前聚焦的内容......)如您所见,我只是覆盖了事件并手动关闭我的组件

Unfortunately, this does not cover all the cases. I also had for some reason (hello buggy AvalonDock) to actually catch the click on the close button because there is an edge case: If you remove the last component, you won't be able to add a new component, because AvalonDockwill remove the last remaining panel. Moreover, if you close a DockableContentwith many tabs in it, AvalonDockwill close all the tabs, so I had to implement something to just close the current tab (which makes more sense imho) I had to add a mouse down handler to each content added to catch this event. With the following trick, I could do a workaround to avoid this bug:

不幸的是,这并不涵盖所有情况。我也出于某种原因(你好,有车的 AvalonDock)实际上抓住了关闭按钮的点击,因为有一个边缘情况:如果你删除最后一个组件,你将无法添加一个新组件,因为AvalonDock将删除最后剩下的面板。此外,如果您关闭一个DockableContent包含许多选项卡的选项卡,AvalonDock将关闭所有选项卡,因此我必须执行一些操作来关闭当前选项卡(恕我直言,这更有意义)我必须为添加到的每个内容添加一个鼠标按下处理程序抓住这个事件。使用以下技巧,我可以采取一种解决方法来避免此错误:

    /// <summary>
    /// Handler called when a DockableContent state changed.
    /// We need it to define a PreviewMouseDownHandler for each DockablePane
    /// possibly created (which are usually created upon docking a floating window
    /// to a new position) in order to handle single DockableContent closing
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void NewContent_StateChanged(object sender, RoutedEventArgs e)
    {
        DockableContent source = sender as DockableContent;
        if (source.State == DockableContentState.Docked && source.Parent is DockablePane)
        {
            DockablePane parent = source.Parent as DockablePane;
            parent.PreviewMouseDown -= mouseHandler;
            parent.PreviewMouseDown += mouseHandler;
        }
    }

    /// <summary>
    /// Handler called on mouse down on a DockablePane.
    /// It is designed to detect where did the user click, and 
    /// if he clicked on Close, only the current DockableContent will be closed
    /// (unlike the native behavior which requires us to close the entire DockablePane
    /// upon clicking on Close...)
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    void DockablePaneMouseDown(object sender, MouseButtonEventArgs e)
    {
        DockablePane source = sender as DockablePane;
        if (e.OriginalSource is AvalonDock.ImageEx)
        {
            //User clicked on one of the three icons on the top-right corner of the DockablePane
            if ((e.OriginalSource as AvalonDock.ImageEx).Source.ToString().Contains("PinClose"))
            {
                RemoveFromUI(source.SelectedItem as DockableContent);
                e.Handled = true;
            }
        }
    }

    /// <summary>
    /// Removes a DockableContent from the currently displayed UI
    /// (called when the original DockableItemsSource changed)
    /// </summary>
    /// <param name="content">The content to be removed</param>
    private void RemoveFromUI(DockableContent content)
    {
        if (content == null)
        {
            return;
        }
        DockablePane parent = content.Parent as DockablePane;
        if (this.ActiveContent == parent.SelectedItem)
        {
            this.ActiveContent = null;
        }
        (parent.SelectedItem as DockableContent).Close();
        //// If the current DockablePane is left empty, we ensure to close it
        if (parent.Items.Count == 0)
        {
            //This case is needed if we are trying to remove the last DockablePane from a DockingManager
            //Native behavior will NOT set the Content property if you remove the last DockablePane:
            //it will therefore consider this CLOSED DockablePane as the current ActiveContent,
            //and will try to add new contents in this closed pane, which seems rather disturbing.
            //Here we explicitly set the Content property to null if we are removing the last element,
            //so next time user adds a tab, it will be added as the new Content!
            if (parent == this.Content)
            {
                this.Content = null;
            }
            parent.Close();
            parent.Visibility = Visibility.Hidden;
        }
    }

Again, this is an incredible big work for such small matters, but unfortunately, this AvalonDockis far from being production-environment ready and I had to tweak such things to make it work.

同样,对于这么小的事情来说,这是一项令人难以置信的大工作,但不幸的是,这AvalonDock远未准备好生产环境,我不得不调整这些事情以使其工作。

Hope it'll work for you as well and save yourself some headaches I've already given to this problem!

希望它也适用于您,并为自己省去一些我已经为这个问题而烦恼的问题!

回答by Vaccano

If you are using the MVVM approach to Avalon Dock (version 2) then you can put this in your view model:

如果您对 Avalon Dock(版本 2)使用 MVVM 方法,那么您可以将其放入您的视图模型中:

DockAsDocumentCommand = new DelegateCommand(() => { }, () => false);
AutoHideCommand = new DelegateCommand(() => { }, () => false);
CanClose = false;
CanHide = false;

Those all need to have TwoWay bindings and NotifyPropertyChanged on them.

这些都需要在其上具有 TwoWay 绑定和 NotifyPropertyChanged。

Once you do that all the options for closing, hiding and moving to another document will be removed or grayed out.

一旦你这样做了,所有关闭、隐藏和移动到另一个文档的选项都将被删除或变灰。

回答by Marc Borgers

If you use MVVM, setting it CanClose to false in XAML is sufficient,like this:

如果您使用 MVVM,在 XAML 中将其 CanClose 设置为 false 就足够了,如下所示:

        <avalondock:DockingManager.LayoutItemContainerStyleSelector>
            <avalon:PanesStyleSelector>
                <avalon:PanesStyleSelector.DeviceStyle>
                    <Style TargetType="{x:Type avalondock:LayoutItem}">
                        <Setter Property="Title" Value="{Binding Model.Name}"/>
                        <Setter Property="ToolTip" Value="{Binding Model.Name}"/>
                        <Setter Property="ContentId" Value="{Binding Model.Id}"/>
                        <Setter Property="CanClose" Value="False"></Setter>
                    </Style>
                </avalon:PanesStyleSelector.DeviceStyle>
            </avalon:PanesStyleSelector>
        </avalondock:DockingManager.LayoutItemContainerStyleSelector>

回答by dotNET

Another way to get rid of Close, CloseAlland CloseAllButThiscommands is to set their commands to null in LayoutItemContainerStyleSelector. Something like:

摆脱Close,CloseAllCloseAllButThis命令的另一种方法是在LayoutItemContainerStyleSelector. 就像是:

<xcad:DockingManager.LayoutItemContainerStyleSelector>
    <local:PanesStyleSelector>
      <local:PanesStyleSelector.DocStyle>
          <Setter Property="CloseCommand" Value="{Binding Model.CloseCommand}"/>
          <Setter Property="CloseAllCommand" Value="{x:Null}" />
          <Setter Property="CloseAllButThisCommand" Value="{x:Null}" />
        </Style>
      </local:PanesStyleSelector.DrawingStyle>
    </local:PanesStyleSelector>
  </xcad:DockingManager.LayoutItemContainerStyleSelector>

PanesStyleSelectoris a simple StyleSelector(I had multiple styles to select from depending upon the pane type, so I needed a StyleSelector; you may want to skip it if you have only one type of pane. Following is the simplified version.):

PanesStyleSelector很简单StyleSelector(根据窗格类型,我有多种样式可供选择,所以我需要一个StyleSelector;如果只有一种类型的窗格,您可能想跳过它。以下是简化版本。):

Public Class PanesStyleSelector
  Inherits StyleSelector

  Public Property DocStyle() As Style

  Public Overrides Function SelectStyle(item As Object, container As System.Windows.DependencyObject) As System.Windows.Style
    Return DocStyle
  End Function
End Class

This will disable both CloseAlland CloseAllButThiscommands in the context menu of the document tabs. Also note that I'm handling CloseCommandin my VM, which I can decide whether to close my document or maybe prompt user about it. This will get rid of the accidental clicking of the close button.

这将禁用文档选项卡上下文菜单中的CloseAllCloseAllButThis命令。另请注意,我正在CloseCommand我的 VM 中处理,我可以决定是关闭我的文档还是提示用户。这将消除意外点击关闭按钮。