防止对接AvalonDock

问题描述 投票:1回答:3

是否可以通过一些过滤来防止将一个可锚定元素对接到另一个可锚定元素?例如,在viewmodel我可以包含一些属性doctype。对于一个可锚定元素,doctype的值将是“a”,而另一个是“b”。如果具有值“a”的可锚定元素无法与doctype“b”对接到可锚定元素,我如何使用属性doctype来防止对接?也许,还有其他解决方案。

c# wpf avalondock
3个回答
0
投票

我在LayoutAnchorableFloatingWindowControl.cs中更改了IOverlayWindowHost.GetDropAreas方法

第一步是初始化内容类型。

var floatingWindowContentHost = Content as FloatingWindowContentHost;
if (floatingWindowContentHost == null) return _dropAreas;
var rootVisual = floatingWindowContentHost.RootVisual;
Type type = null;

var layoutAnchorableFloatingWindow = draggingWindow.Model as LayoutAnchorableFloatingWindow;
if (layoutAnchorableFloatingWindow != null)
{
    //big part of code for getting type
    var layoutAnchorablePane = layoutAnchorableFloatingWindow.SinglePane as LayoutAnchorablePane;

    if (layoutAnchorablePane != null
        && (layoutAnchorableFloatingWindow.IsSinglePane
        && layoutAnchorablePane.SelectedContent != null))
    {
        var layoutAnchorable = ((LayoutAnchorablePane)layoutAnchorableFloatingWindow.SinglePane).SelectedContent as LayoutAnchorable;
        if (layoutAnchorable != null)
            type = layoutAnchorable.Content;
    }
    else
    {
        var pane = GetLayoutAnchorablePane(layoutAnchorableFloatingWindow.RootPanel);
        if (pane == null || pane.SelectedContent == null) 
            return null;

        var layoutAnchorable = pane.SelectedContent as LayoutAnchorable;
        if (layoutAnchorable != null)
            type = layoutAnchorable.Content;
    }
}

在此之后我只是比较两种类型并将需要放入_dropAreas

foreach (var areaHost in rootVisual.FindVisualChildren<LayoutAnchorablePaneControl>())
{
    Type areahostType = null;
    var layoutAnchorablePane = areaHost.Model as LayoutAnchorablePane;
    if (layoutAnchorablePane != null && layoutAnchorablePane.SelectedContent != null)
    {
        var layoutAnchorable = ((LayoutAnchorablePane)areaHost.Model).SelectedContent as LayoutAnchorable;
        if (layoutAnchorable != null)
            areahostType = layoutAnchorable.Content;
    }
    // prevent docking different documents
    if (type != null && areahostType != null && areahostType == type)
    {
        _dropAreas.Add(new DropArea<LayoutAnchorablePaneControl>( areaHost, DropAreaType.AnchorablePane));
    }
}

为防止停靠到文档区域,需要在DockingManager.cs中对同一方法进行更改

对于DropTargets的视觉防止需要更改OverlayWindow.cs


0
投票

改变IOverlayWindowHost.GetDropAreas是正确的,但这种变化对我来说似乎更容易。

我在“LayoutAnchorableFloatingWindowControl.cs”中简单地删除了这个foreach:

...
// Remove this foreach
foreach (var areaHost in rootVisual.FindVisualChildren<LayoutDocumentPaneControl>())
{
    _dropAreas.Add(new DropArea<LayoutDocumentPaneControl>(
        areaHost,
        DropAreaType.DocumentPane));
}

return _dropAreas;

在“DockingManager.cs”中的其他实现中,您必须添加其他原因:

if (!isDraggingDocuments)
{
    _areas.Add(new DropArea<DockingManager>(
        this,
        DropAreaType.DockingManager));

    foreach (var areaHost in this.FindVisualChildren<LayoutAnchorablePaneControl>())
    {
        if (areaHost.Model.Descendents().Any())
        {
            _areas.Add(new DropArea<LayoutAnchorablePaneControl>(
                areaHost,
                DropAreaType.AnchorablePane));
        }
    }
}
// -----> This else is new
else
{ 
    foreach (var areaHost in this.FindVisualChildren<LayoutDocumentPaneControl>())
    {
        _areas.Add(new DropArea<LayoutDocumentPaneControl>(
            areaHost,
            DropAreaType.DocumentPane));
    }

    foreach (var areaHost in this.FindVisualChildren<LayoutDocumentPaneGroupControl>())
    {
        var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup;
        if (documentGroupModel.Children.Where(c => c.IsVisible).Count() == 0)
        {
            _areas.Add(new DropArea<LayoutDocumentPaneGroupControl>(
                areaHost,
                DropAreaType.DocumentPaneGroup));
        }
    }
}

return _areas;

因此,如果您没有拖动LayoutDocument,请不要将文档窗格控件添加到放置区域。

多数民众赞成 - 对我有用。


0
投票

在AvalonDock 3.5(我认为3.2)中有一个LayoutAnchorable属性CanDockAsTabbedDocument,可以设置为false以防止工具窗口停靠在DocumentPane中。这仅适用于AvalonDock 3.8 and earlier中的上下文菜单,而拖放行为仍然存在问题。

但是您可以使用此修复程序来获得AvalonDock 3.5的预期拖放行为。下面的代码扩展了IOverlayWindowHost.GetDropAreas中的DockingManager.cs

这个解决方案的关键是dockAsDocument布尔变量。它保护foreach循环,负责将任何项目插入DocumentsPaneMainWindow

只要有一个dockAsDocument(工具窗口)可以在LayoutAnchorable中找到并配置了LayoutFloatingWindowControlCanDockAsTabbedDocument="False"变量就会设置为false。

IEnumerable<IDropArea> IOverlayWindowHost.GetDropAreas( LayoutFloatingWindowControl draggingWindow )
{
  if( _areas != null )
    return _areas;

  bool isDraggingDocuments = draggingWindow.Model is LayoutDocumentFloatingWindow;

  _areas = new List<IDropArea>();

  if( !isDraggingDocuments )
  {
    _areas.Add( new DropArea<DockingManager>(
        this,
        DropAreaType.DockingManager ) );

    foreach( var areaHost in this.FindVisualChildren<LayoutAnchorablePaneControl>() )
    {
      if( areaHost.Model.Descendents().Any() )
      {
        _areas.Add( new DropArea<LayoutAnchorablePaneControl>(
            areaHost,
            DropAreaType.AnchorablePane ) );
      }
    }
  }

  // Determine if floatingWindow is configured to dock as document or not
  bool dockAsDocument = true;
  if (isDraggingDocuments == false)
  {
    var toolWindow = draggingWindow.Model as LayoutAnchorableFloatingWindow;
    if (toolWindow != null)
    {
      foreach (var item in GetAnchorableInFloatingWindow(draggingWindow))
      {
        if (item.CanDockAsTabbedDocument == false)
        {
          dockAsDocument = false;
          break;
        }
      }
    }
  }

  // Dock only documents and tools in DocumentPane if configuration does allow that
  if (dockAsDocument == true)
  {
    foreach( var areaHost in this.FindVisualChildren<LayoutDocumentPaneControl>() )
    {
      _areas.Add( new DropArea<LayoutDocumentPaneControl>(
          areaHost,
          DropAreaType.DocumentPane ) );
    }
  }

  foreach( var areaHost in this.FindVisualChildren<LayoutDocumentPaneGroupControl>() )
  {
    var documentGroupModel = areaHost.Model as LayoutDocumentPaneGroup;
    if( documentGroupModel.Children.Where( c => c.IsVisible ).Count() == 0 )
    {
      _areas.Add( new DropArea<LayoutDocumentPaneGroupControl>(
          areaHost,
          DropAreaType.DocumentPaneGroup ) );
    }
  }

  return _areas;
}

/// <summary>
/// Finds all <see cref="LayoutAnchorable"/> objects (toolwindows) within a
/// <see cref="LayoutFloatingWindow"/> (if any) and return them.
/// </summary>
/// <param name="draggingWindow"></param>
/// <returns></returns>
private IEnumerable<LayoutAnchorable> GetAnchorableInFloatingWindow(LayoutFloatingWindowControl draggingWindow)
{
  var layoutAnchorableFloatingWindow = draggingWindow.Model as LayoutAnchorableFloatingWindow;
  if (layoutAnchorableFloatingWindow != null)
  {
      //big part of code for getting type
      var layoutAnchorablePane = layoutAnchorableFloatingWindow.SinglePane as LayoutAnchorablePane;

      if (layoutAnchorablePane != null
          && (layoutAnchorableFloatingWindow.IsSinglePane
          && layoutAnchorablePane.SelectedContent != null))
      {
          var layoutAnchorable = ((LayoutAnchorablePane)layoutAnchorableFloatingWindow.SinglePane).SelectedContent as LayoutAnchorable;
          yield return layoutAnchorable;
      }
      else
      {
        foreach (var item in GetLayoutAnchorable(layoutAnchorableFloatingWindow.RootPanel))
        {
          yield return item;
        }
      }
  }
}

/// <summary>
/// Finds all <see cref="LayoutAnchorable"/> objects (toolwindows) within a
/// <see cref="LayoutAnchorablePaneGroup"/> (if any) and return them.
/// </summary>
/// <param name="layoutAnchPaneGroup"></param>
/// <returns></returns>
internal IEnumerable<LayoutAnchorable> GetLayoutAnchorable(LayoutAnchorablePaneGroup layoutAnchPaneGroup)
{
  if (layoutAnchPaneGroup != null)
  {
    foreach (var anchorable in layoutAnchPaneGroup.Descendents().OfType<LayoutAnchorable>())
    {
      yield return anchorable;
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.