4

これは私に多くの問題を引き起こしているので、私はそれらを削除したいと思います。それを解決する方法があれば、私はそれを試して喜んでいます。それを使用して最初の数分間は、3つの異なる例外のようになり、それらの気の利いたオプションを削除する方法がわかりません。

オブジェクトの現在の状態が原因で操作が無効であるため、ピン留めおよびピン留め解除とピン留めは、InvalidOperationExceptionをスローします。

固定と固定解除によってダイアログボックスが開き、ファイルを要求されることがあります。これは発生させたくありませんが、発生していて例外がスローされます。

誤って閉じるボタンをクリックしてしまい、ウィンドウを元に戻すことができません。本当にイライラします。他のavalondockユーザーがこれに出くわしたと確信しています。

そして、あまり時間を無駄にしたくないので、ここでお聞きします。この例外をどのように回避したか、またはそれらのボタンを削除しましたか?ありがとう。

4

4 に答える 4

3

私はあなたとまったく同じ問題を抱えていました。実際のUIからアイコンを削除したくないので、イベントハンドラーでアイコンを無効にしました

これが私がどのように働いたかです:

これらの非表示および自動非表示コマンドを削除するには:

次のハンドラーを追加しました。

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、フォーカスがあるために別のコンテンツを閉じることがあります(十字をクリックしてもコンテンツにフォーカスが合わないため、現在フォーカスされているコンテンツが閉じられます...)ご覧のとおり、私はイベントを実行し、コンポーネントを手動で閉じます

残念ながら、これはすべてのケースを網羅しているわけではありません。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;
        }
    }

繰り返しになりますが、これはそのような小さな問題に対しては信じられないほど大きな作業ですが、残念ながら、これAvalonDockは本番環境に対応できる状態にはほど遠いので、それを機能させるためにそのようなことを微調整する必要がありました。

それがあなたにもうまくいくことを願って、私がこの問題にすでに与えたいくつかの頭痛をあなた自身に救ってください!

于 2012-08-16T15:29:41.050 に答える
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 に答える
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、でコマンドをnullに設定することです。何かのようなもの:CloseAllCloseAllButThisLayoutItemContainerStyleSelector

<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;が必要でした。ペインのタイプが1つしかない場合は、スキップすることをお勧めします。以下は簡略化されたバージョンです。):

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

これにより、ドキュメントタブのコンテキストメニューのコマンドCloseAllとコマンドの両方が無効になります。CloseAllButThisまた、VMで処理していることにも注意してくださいCloseCommand。これにより、ドキュメントを閉じるか、ユーザーにそのことを促すかを決定できます。これにより、閉じるボタンを誤ってクリックすることがなくなります。

于 2016-08-30T06:50:02.073 に答える