4

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

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

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

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

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

4

4 回答 4

3

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

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

这些都需要有 TwoWay 绑定和 NotifyPropertyChanged。

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

于 2012-08-17T17:06:30.737 回答
3

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

这是我的工作方式:

要删除那些 Hide 和 AutoHide 命令:

我添加了以下处理程序:

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

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;

} }

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

不幸的是,这并没有涵盖所有情况。出于某种原因(hello buggy AvalonDock),我也有实际捕获关闭按钮的点击,因为有一个边缘情况:如果您删除最后一个组件,您将无法添加新组件,因为AvalonDock将删除最后剩下的面板。此外,如果您关闭其中DockableContent包含许多选项卡的 a,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;
        }
    }

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

希望它也对你有用,并为你自己省去一些我已经给这个问题带来的头痛!

于 2012-08-16T15:29:41.050 回答
2

如果您使用 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>
于 2015-09-17T08:14:03.000 回答
0

摆脱Close,CloseAllCloseAllButThis命令的另一种方法是将它们的命令设置为 null in 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>

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

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

于 2016-08-30T06:50:02.073 回答