Использование шаблона MVVM для заполнения элементами закрепления¶
Контрол DockManager
позволяет использовать шаблон проектирования MVVM для заполнения контрола элементами закрепления (например, объектами DocumentPane
и DockPane
). При этой технике вы назначаете коллекцию элементов закрепления компоненту DockManager
и указываете шаблон, используемый для отрисовки элементов закрепления.
Заполнение DockManager элементами из источника данных¶
Используйте свойство DockManager.ItemsSource
для привязки DockManager
к коллекции объектов, которые необходимо отобразить как элементы закрепления. Способ преобразования этих объектов в элементы закрепления задаётся свойством DockManager.ItemTemplate
.
Чтобы указать шаблон для отрисовки содержимого элементов закрепления, созданных из коллекции DockManager.ItemsSource
, используйте свойство DockManager.ItemContentTemplate
.
Следующий пример из демо IDE Layout использует свойство DockManager.ItemsSource
для привязки контрола к коллекции Documents, определённой в главной View Model. Элементы этой коллекции (объекты IdeLayoutDocumentViewModel) отображаются как объекты DocumentPane
.
<mxd:DockManager Grid.Column="0" Grid.Row="1"
BorderThickness="0"
ItemsSource="{Binding Documents}"
ItemContentTemplate="{views:IdeLayoutDocumentContentTemplate}">
<mxd:DockManager.ItemTemplate>
<DataTemplate DataType="vm:IdeLayoutDocumentViewModel">
<mxd:DocumentPane Header="{Binding Header}"
IsActive="{Binding IsActive}"
CloseCommand="{Binding CloseCommand}"/>
</DataTemplate>
</mxd:DockManager.ItemTemplate>
<mxd:DockGroup>
<!-- ... -->
<!-- Created DocumentPane objects are placed in the first DocumentGroup container. -->
<mxd:DocumentGroup DockWidth="5*">
</mxd:DocumentGroup>
</mxd:DockGroup>
</mxd:DockManager>
public partial class IdeLayoutPageViewModel : PageViewModelBase
{
public ObservableCollection<IdeLayoutDocumentViewModel> Documents { get; };
//...
}
public partial class IdeLayoutDocumentViewModel : ObservableObject
{
[ObservableProperty] private string header;
[ObservableProperty] private string uri;
[ObservableProperty] private bool isActive;
[ObservableProperty] private ICommand closeCommand;
}
public class IdeLayoutDocumentContentTemplate : MarkupExtension, IDataTemplate
{
//...
}
См. полный код этого примера в модуле IDE Layout Демо-приложения.
Note
Когда объекты DocumentPane
создаются из коллекции DockManager.ItemsSource
, они автоматически отображаются как вкладки в первом контейнере DocumentGroup
. Убедитесь, что DockManager
имеет хотя бы один контейнер DocumentGroup
. Вы можете реализовать адаптер элементов (DockManager.ItemAdapter
), чтобы размещать созданные элементы закрепления (например, объекты DocumentPane
) в определённом контейнере закрепления. Для получения более подробной информации см. следующий раздел.
Создание различных типов элементов закрепления из источника данных¶
Вы можете захотеть привязать свойство DockManager.ItemsSource
к коллекции объектов, которые должны отображаться как панели закрепления, документы, автоматически скрываемые панели и/или плавающие панели. Для выполнения этой задачи используйте следующий подход:
- Реализуйте селектор шаблонов, который создаёт определённые элементы закрепления из объектов в коллекции
DockManager.ItemsSource
. - Добавьте контейнеры закрепления в компонент
DockManager
, которые должны размещать созданные элементы закрепления. - Создайте адаптер элементов, который помещает созданные элементы закрепления в определённые контейнеры закрепления.
Пример¶
-
Определите коллекцию Panes в главной View Model. Эта коллекция будет содержать следующие элементы:
-
Объекты DockPaneViewModel - Эти объекты должны отображаться как панели закрепления (
DockPane
). - Объекты DocumentPaneViewModel - Эти объекты должны отображаться как панели документов (
DocumentPane
).
namespace EremexAvaloniaApplication1;
public class MainViewModel : ObservableObject
{
public ObservableCollection<PaneViewModelBase> Panes { get; } = new();
}
public partial class PaneViewModelBase : ObservableObject
{
[ObservableProperty] private string? header;
}
public class DockPaneViewModel : PaneViewModelBase { }
public class DocumentPaneViewModel : PaneViewModelBase { }
- Инициализируйте коллекцию Panes примерами объектов.
namespace EremexAvaloniaApplication1;
public partial class MainWindow : MxWindow
{
public MainWindow()
{
var viewModel = new MainViewModel();
viewModel.Panes.AddRange(new PaneViewModelBase[]
{
new DockPaneViewModel() { Header = "Pane1" },
new DockPaneViewModel() { Header = "Pane2" },
new DockPaneViewModel() { Header = "Pane3" },
new DocumentPaneViewModel() { Header = "Doc1" },
new DocumentPaneViewModel() { Header = "Doc2" }
});
DataContext = viewModel;
InitializeComponent();
}
}
-
Определите компонент
DockManager
в главном окне. Привяжите его к коллекции MainViewModel.Panes и создайте два контейнера закрепления: -
paneHost — Контейнер
DockGroup
, который должен отображать панели закрепления, созданные из объектов DockPaneViewModel. - documentHost – Контейнер
DocumentGroup
, который должен отображать панели документов, созданные из объектов DocumentPaneViewModel.
<mx:MxWindow xmlns="https://github.com/avaloniaui"
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:mx="https://schemas.eremexcontrols.net/avalonia"
xmlns:mxd="https://schemas.eremexcontrols.net/avalonia/docking"
xmlns:local="clr-namespace:EremexAvaloniaApplication1"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="EremexAvaloniaApplication1.MainWindow"
Icon="/Assets/EMXControls.ico"
Title="EremexAvaloniaApplication1"
x:DataType="local:MainViewModel">
<mxd:DockManager ItemsSource="{Binding Panes}">
<mxd:DockGroup>
<mxd:DockGroup x:Name="paneHost" Orientation="Vertical"></mxd:DockGroup>
<mxd:DocumentGroup x:Name="documentHost"></mxd:DocumentGroup>
</mxd:DockGroup>
</mxd:DockManager>
</mx:MxWindow>
- Реализуйте селектор шаблонов, который создаёт объекты
DockPane
из элементов DockPaneViewModel и объектыDocumentPane
из элементов DocumentPaneViewModel. Назначьте этот селектор шаблонов свойствуDockManager.ItemTemplate
.
namespace EremexAvaloniaApplication1;
public class PaneTemplateSelector : MarkupExtension, IDataTemplate
{
public IDataTemplate? DocumentTemplate { get; set; }
public IDataTemplate? DockPaneTemplate { get; set; }
public Control? Build(object? param)
{
if (param is DocumentPaneViewModel) return DocumentTemplate?.Build(param);
return DockPaneTemplate?.Build(param);
}
public bool Match(object? data)
{
return data is PaneViewModelBase;
}
public override object ProvideValue(IServiceProvider serviceProvider) => this;
}
<mxd:DockManager ItemsSource="{Binding Panes}">
<mxd:DockManager.ItemTemplate>
<local:PaneTemplateSelector>
<local:PaneTemplateSelector.DocumentTemplate>
<DataTemplate DataType="local:DocumentPaneViewModel">
<mxd:DocumentPane Header="{Binding Header}" />
</DataTemplate>
</local:PaneTemplateSelector.DocumentTemplate>
<local:PaneTemplateSelector.DockPaneTemplate>
<DataTemplate DataType="local:DockPaneViewModel">
<mxd:DockPane Header="{Binding Header}" />
</DataTemplate>
</local:PaneTemplateSelector.DockPaneTemplate>
</local:PaneTemplateSelector>
</mxd:DockManager.ItemTemplate>
<mxd:DockGroup>
<mxd:DockGroup x:Name="paneHost" Orientation="Vertical"></mxd:DockGroup>
<mxd:DocumentGroup x:Name="documentHost"></mxd:DocumentGroup>
</mxd:DockGroup>
</mxd:DockManager>
- Создайте адаптер элементов, который помещает созданные объекты
DockPane
иDocumentPane
в соответствующие контейнеры закрепления.
Адаптер элементов - это класс, реализующий интерфейс IDockManagerItemAdapter
. Метод IDockManagerItemAdapter.Adapt
вызывается для каждого элемента закрепления, созданного из коллекции DockManager.ItemsSource
. Этот метод должен разместить элемент закрепления в определённом контейнере закрепления.
Используйте свойство DockManager.ItemAdapter
для указания адаптера элементов.
namespace EremexAvaloniaApplication1;
public class PaneAdapter : MarkupExtension, IDockManagerItemAdapter
{
public void Adapt(DockManager dockManager, DockItemBase dockItem, object item)
{
var target = dockManager.FindItem<DockGroup>(dockItem is DocumentPane ? "documentHost" : "paneHost");
target?.Add(dockItem);
}
public override object ProvideValue(IServiceProvider serviceProvider)
{
return this;
}
}
- Запустите приложение, чтобы увидеть компонент
DockManager
, заполненный элементами закрепления из коллекции Panes.
* Эта страница была переведена с помощью нейросети Deepseek.