我在使用Stylet的AvalonDock first MVVM方法下添加AnchorablesSource时遇到了问题。
我的avalonDock XAML如下:
<DockingManager
Grid.Row="1"
DocumentsSource="{Binding Scl.Documents}"
AnchorablesSource="{Binding Scl.DocumentsAnchorable}"
x:Name="dockManager"
AllowMixedOrientation="True"
AutoWindowSizeWhenOpened="True"
IsVirtualizingAnchorable="True"
IsVirtualizingDocument="True"
ActiveContent="{Binding Scl.ActiveDocument, Mode=TwoWay}"
DocumentClosed="{s:Action DocumentClosed}"
>
<DockingManager.LayoutItemContainerStyle>
<Style TargetType="{x:Type LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
<Setter Property="Height" Value="Auto"/>
<Setter Property="IconSource" Value="{Binding Model.IconSource}" />
</Style>
</DockingManager.LayoutItemContainerStyle>
<DockingManager.LayoutItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<ContentControl s:View.Model="{Binding Content , FallbackValue=#ERROR Content.title#}"></ContentControl>
</Grid>
</DataTemplate>
</DockingManager.LayoutItemTemplate>
<LayoutRoot x:Name="root">
<LayoutPanel Orientation="Horizontal">
<LayoutAnchorablePane x:Name="LayoutAnchorablePane" DockWidth="50">
</LayoutAnchorablePane>
<LayoutDocumentPaneGroup>
<LayoutDocumentPane x:Name="LayoutDocumentPane">
<!-- This is where the new windows are typically added -->
</LayoutDocumentPane>
</LayoutDocumentPaneGroup>
<LayoutAnchorablePaneGroup DockWidth="250">
<LayoutAnchorablePane x:Name="LayoutAnchorablePane1">
</LayoutAnchorablePane>
</LayoutAnchorablePaneGroup>
</LayoutPanel>
<LayoutRoot.LeftSide>
<LayoutAnchorSide>
<LayoutAnchorGroup>
</LayoutAnchorGroup>
</LayoutAnchorSide>
</LayoutRoot.LeftSide>
</LayoutRoot>
</DockingManager>
在我的ViewModel
中有:
public ObservableCollection<LayoutDocument> Documents {get; set;} = new ObservableCollection<LayoutDocument>();
public ObservableCollection<LayoutAnchorable> DocumentsAnchorable { get; set; } = new ObservableCollection<LayoutAnchorable>();
当我向LayoutDocumentPane
添加一个新的普通布局时,如下所示,它工作得很好:
public void NewLayout(Screen viewModel, string title)
{
if (IsOpen(title) == true)
{
return;
}
LayoutDocument layout = new LayoutDocument
{
Title = title,
Content = viewModel
};
Documents.Add(layout);
Documents.Move(Documents.Count - 1, 0);
ActiveDocument = layout;
}
但是,如果尝试添加一个新的可锚定布局(即使像这样知道工作的ViewModel
),我也会出错。
public void NewLayoutAnchorable(Screen viewModel, string title)
{
if (IsOpen(title) == true)
{
return;
}
LayoutAnchorable layout = new LayoutAnchorable
{
Title = title,
Content = viewModel
};
DocumentsAnchorable.Add(layout);
//DocumentsAnchorable.Move(Documents.Count - 1, 0);
//ActiveDocument = layout;
}
我得到的错误是:
引发的
异常:抛出的Stylet.dll异常中的“Stylet.StyletViewLocationException”:PresentationFramework.dll中的“System.Windows.Markup.XamlParseException”无法将ViewModel名称AvalonDock.Layout.LayoutAnchorable转换为合适的视图名称
有人知道为什么Stylet可以找到相关的View
,然后ViewModel
用于LayoutDocument
,而不是AvalonDock中的LayoutAnchorable
?
编辑1:
问题似乎与LayoutAnchorable
视图模型无关,因为我可以将它们添加到ObservableCollection<LayoutDocument>
中,这样他们就可以找到一个view
了。只有当我尝试将一个viewmodel
添加到ObservableCollection<LayoutAnchorable>
中才会出现问题,因此它似乎是我的AvalonDock XAML的一个问题。
编辑2:
如果我从我的XAML中删除以下行:
<ContentControl s:View.Model="{Binding Content , FallbackValue=#ERROR Content.title#}"></ContentControl>
我可以通过可观察的集合将ViewModels
添加到两个集合中,并且窗口同时出现在LayoutPane和AchorablePane中,除非窗口缺少它们的内容。
因此,我似乎需要一个适用于可锚窗口的LayoutItemTemplate
,但我似乎找不到一个例子。
编辑3:
我做了一个赤裸裸的项目,如果有人想玩的话,我就在这里演示这个问题。
https://github.com/montyjohn/StyletAvalonDockTest.git
如果Stylet和AvalonDock可以很好地结合在一起,这将是一个很好的起点,所以新的应用程序。
发布于 2022-10-30 18:25:42
我认为DockingManager存在一个问题,因为它为其项目设置了不同的DataContexts。DataContext for ContentControl是LayoutDocument for DocumentPane,但是是ContentPresenter (LayoutAnchorable的父级)表示AnchorablePane。
你可以用这个解决办法。我添加了一个模板选择器和修改过的ShellView.xaml文件。现在起作用了。
ShellView.xaml
<Window x:Class="StyletAvalonDockTest.Views.ShellView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ts="clr-namespace:StyletAvalonDockTest.TemplateSelectors"
xmlns:s="https://github.com/canton7/Stylet"
mc:Ignorable="d"
Title="ShellView" Height="450" Width="800">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Horizontal">
<Button Width="auto" Command="{s:Action NewLayout}">Add New Window</Button>
<Button Width="auto" Command="{s:Action NewLayoutAnchorable}">Add New Anchorable Pane</Button>
</StackPanel>
<DockingManager
Grid.Row="1"
DocumentsSource="{Binding Documents}"
AnchorablesSource="{Binding DocumentsAnchorable}"
>
<!--If the theme is removed, neither the new Layout, nor the New Anchorable Layout work-->
<DockingManager.Theme>
<Vs2013LightTheme />
</DockingManager.Theme>
<!--This adds the title to the new windows-->
<DockingManager.LayoutItemContainerStyle>
<Style TargetType="{x:Type LayoutItem}">
<Setter Property="Title" Value="{Binding Model.Title}"/>
</Style>
</DockingManager.LayoutItemContainerStyle>
<DockingManager.LayoutItemTemplateSelector>
<ts:PanesTemplateSelector>
<ts:PanesTemplateSelector.DocumentPaneTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding Content}"/>
</DataTemplate>
</ts:PanesTemplateSelector.DocumentPaneTemplate>
<ts:PanesTemplateSelector.AnchoroblePaneTemplate>
<DataTemplate>
<ContentControl s:View.Model="{Binding Content.Content}"/>
</DataTemplate>
</ts:PanesTemplateSelector.AnchoroblePaneTemplate>
</ts:PanesTemplateSelector>
</DockingManager.LayoutItemTemplateSelector>
<LayoutRoot>
<LayoutPanel>
<LayoutAnchorablePane>
<!-- This is where the new Anchorable windows are added -->
</LayoutAnchorablePane>
<LayoutDocumentPaneGroup>
<LayoutDocumentPane>
<!-- This is where the new windows are added -->
</LayoutDocumentPane>
</LayoutDocumentPaneGroup>
</LayoutPanel>
</LayoutRoot>
</DockingManager>
</Grid>
PanesTemplateSelector.cs
using AvalonDock.Layout;
using System.Windows;
using System.Windows.Controls;
namespace StyletAvalonDockTest.TemplateSelectors
{
public class PanesTemplateSelector : DataTemplateSelector
{
public DataTemplate DocumentPaneTemplate { get; set; }
public DataTemplate AnchoroblePaneTemplate { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
if (item is LayoutDocument)
return DocumentPaneTemplate;
else
return AnchoroblePaneTemplate;
}
}
}
https://stackoverflow.com/questions/74186935
复制相似问题