首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >首先使用MVVM AnchorablesSource在AvalonDock中添加ViewModel

首先使用MVVM AnchorablesSource在AvalonDock中添加ViewModel
EN

Stack Overflow用户
提问于 2022-10-24 21:21:05
回答 1查看 74关注 0票数 1

我在使用Stylet的AvalonDock first MVVM方法下添加AnchorablesSource时遇到了问题。

我的avalonDock XAML如下:

代码语言:javascript
运行
复制
<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中有:

代码语言:javascript
运行
复制
public ObservableCollection<LayoutDocument> Documents {get; set;} = new ObservableCollection<LayoutDocument>();
public ObservableCollection<LayoutAnchorable> DocumentsAnchorable { get; set; } = new ObservableCollection<LayoutAnchorable>();

当我向LayoutDocumentPane添加一个新的普通布局时,如下所示,它工作得很好:

代码语言:javascript
运行
复制
    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 ),我也会出错。

代码语言:javascript
运行
复制
    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中删除以下行:

代码语言:javascript
运行
复制
<ContentControl s:View.Model="{Binding Content , FallbackValue=#ERROR Content.title#}"></ContentControl>

我可以通过可观察的集合将ViewModels添加到两个集合中,并且窗口同时出现在LayoutPane和AchorablePane中,除非窗口缺少它们的内容。

因此,我似乎需要一个适用于可锚窗口的LayoutItemTemplate,但我似乎找不到一个例子。

编辑3:

我做了一个赤裸裸的项目,如果有人想玩的话,我就在这里演示这个问题。

https://github.com/montyjohn/StyletAvalonDockTest.git

如果Stylet和AvalonDock可以很好地结合在一起,这将是一个很好的起点,所以新的应用程序。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-30 18:25:42

我认为DockingManager存在一个问题,因为它为其项目设置了不同的DataContexts。DataContext for ContentControl是LayoutDocument for DocumentPane,但是是ContentPresenter (LayoutAnchorable的父级)表示AnchorablePane。

你可以用这个解决办法。我添加了一个模板选择器和修改过的ShellView.xaml文件。现在起作用了。

ShellView.xaml

代码语言:javascript
运行
复制
<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

代码语言:javascript
运行
复制
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;
        }
    }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74186935

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档