Table of Contents

Строки в контроле PropertyGrid

PropertyGrid может автоматически создавать строки для свойств, предоставляемых привязанным объектом(ами) (см. PropertyGridControl.SelectedObject и PropertyGridControl.SelectedObjects). Автоматическая генерация строк включена по умолчанию. Вы можете отключить автоматическую генерацию строк с помощью опции PropertyGridControl.AutoGenerateRows, а затем создавать строки вручную.

propertygrid-sample

PropertyGrid поддерживает три типа строк:

  • Обычные строки (данных) (PropertyGridRow) — Отображают имена и значения привязанных свойств.

    data-rows

  • Категориальные строки (PropertyGridCategoryRow) — используется для группировки других строк по категориям. Пользователи могут сворачивать и разворачивать категориальные строки, чтобы скрыть/показать их дочерние элементы.

    category-rows

  • Табуляционная строка (PropertyGridTabRow) — используется для организации строк в пользовательский интерфейс с вкладками. Табуляционные строки не поддерживают функцию сворачивания/развертывания.

    property-grid-tab-rows

Создание строк

При включенной функции автоматической генерации строк пустой контрол PropertyGrid создает данные и категориальные строки на основе информации, полученной из привязанного объекта:

  • Обычные строки создаются для всех публичных свойств.
  • Категориальные строки генерируются на основе атрибутов System.ComponentModel.CategoryAttribute, применяемых к нижележащим публичным свойствам. Соответствующие строки данных сгруппированы в пределах этих категорий.

Если какая-либо строка была добавлена в контрол вручную (например, в XAML), автоматическая генерация строк не выполняется. Установите для свойства PropertyGridControl.AutoGenerateRows значение false, чтобы принудительно отключить автоматическую генерацию строк.

Используйте метод PopulateRows в коде для генерации данных и категориальных строк из привязанного объекта(ов). Этот метод очищает существующую коллекцию строк перед добавлением новых строк.

Вы можете применить определенные атрибуты Data Annotation к свойствам привязанного объекта, чтобы контролировать наличие, отображаемое имя и статус только для чтения сгенерированных строк PropertyGrid. Смотрите следующий раздел для получения более подробной информации: Использование атрибутов для настройки свойств строк .

Коллекция PropertyGridControl.Rows позволяет вам получать доступ к строкам контрола, добавлять и удалять отдельные элементы.

Создание строк данных

Используйте объекты PropertyGridRow для создания строк данных. Чтобы добавить строки данных на корневом уровне, добавьте объекты PropertyGridRow в коллекцию PropertyGridControl.Rows.

Основные свойства класса PropertyGridRow включают:

  • PropertyGridRow.FieldName — Получает или задает имя публичного свойства, к которому привязана строка.
  • PropertyGridRow.Caption — Получает или задает заголовок строки. Для автоматически сгенерированных строк свойство Caption содержит отображаемое имя свойства.
  • PropertyGridRow.AllowEditing — Возвращает или устанавливает, включены ли операции редактирования значений.
  • PropertyGridRow.EditorProperties — Позволяет вам назначить пользовательский встроенный редактор значению строки. Смотрите Редактирование данных .

Пример

Следующий код XAML создает три строки данных (объекты PropertyGridRow) и привязывает их к полям объекта, назначенного контексту данных контрола.

xmlns:mxpg="clr-namespace:Eremex.AvaloniaUI.Controls.PropertyGrid;assembly=Eremex.Avalonia.Controls"

<mxpg:PropertyGridControl x:Name="pGrid1" SelectedObject="{Binding}" Grid.Column="1">
    <mxpg:PropertyGridRow FieldName="Caption">
    </mxpg:PropertyGridRow>
    <mxpg:PropertyGridRow FieldName="OrderNo">
    </mxpg:PropertyGridRow>
    <mxpg:PropertyGridRow FieldName="InvoiceNo">
    </mxpg:PropertyGridRow>
</mxpg:PropertyGridControl>

Пример

Следующий пример создает строки данных в коде:

xmlns:mxpg="clr-namespace:Eremex.AvaloniaUI.Controls.PropertyGrid;assembly=Eremex.Avalonia.Controls"

<mxpg:PropertyGridControl x:Name="pGrid1" AutoGenerateRows="False" SelectedObject="{Binding}" Grid.Column="1">
</mxpg:PropertyGridControl>
using Eremex.AvaloniaUI.Controls.PropertyGrid;

pGrid1.Rows.Add(new PropertyGridRow() { FieldName = "Caption" });
pGrid1.Rows.Add(new PropertyGridRow() { FieldName = "OrderNo" });
pGrid1.Rows.Add(new PropertyGridRow() { FieldName = "InvoiceNo" });

Создание категориальных строк

PropertyGrid может генерировать категориальные строки из атрибутов System.ComponentModel.CategoryAttribute, применяемых к нижележащим публичным свойствам. Соответствующие строки данных сгруппированы в этих категориальных строках.

Вы можете отключить автоматическую генерацию строк и создать пользовательский набор строк данных и категориальных строк. Используйте объекты PropertyGridCategoryRow для определения категориальных строк. Добавьте объекты PropertyGridCategoryRow в коллекцию PropertyGridControl.Rows, чтобы отобразить их на корневом уровне.

Основные свойства класса PropertyGridCategoryRow включают:

  • PropertyGridCategoryRow.Rows — Коллекция строк, отображаемых как дочерние элементы категориальной строки. Как правило, вы добавляете строки данных (объекты PropertyGridRow) в эту коллекцию.
  • PropertyGridCategoryRow.Caption — Получает или задает отображаемое имя категориальной строки. Для автоматически сгенерированных категориальных строк это свойство возвращает значение CategoryAttribute.

Пример

Следующий XAML-код создает две категориальные строки (Name и Details). Они имеют одну и две строки данных в качестве дочерних, соответственно.

xmlns:mxpg="clr-namespace:Eremex.AvaloniaUI.Controls.PropertyGrid;assembly=Eremex.Avalonia.Controls"
<mxpg:PropertyGridControl x:Name="pGrid1" SelectedObject="{Binding}" Grid.Column="1">
    <mxpg:PropertyGridCategoryRow Caption="Name">
        <mxpg:PropertyGridRow FieldName="Caption">
        </mxpg:PropertyGridRow>
    </mxpg:PropertyGridCategoryRow>
    <mxpg:PropertyGridCategoryRow Caption="Details">
        <mxpg:PropertyGridRow FieldName="OrderNo">
        </mxpg:PropertyGridRow>
        <mxpg:PropertyGridRow FieldName="InvoiceNo">
        </mxpg:PropertyGridRow>
    </mxpg:PropertyGridCategoryRow>
</mxpg:PropertyGridControl>

Пример

Следующий пример создает категориальные строки и помещает строки данных в созданные категории в коде.

xmlns:mxpg="clr-namespace:Eremex.AvaloniaUI.Controls.PropertyGrid;assembly=Eremex.Avalonia.Controls"

<mxpg:PropertyGridControl x:Name="pGrid1" AutoGenerateRows="False" SelectedObject="{Binding}" Grid.Column="1">
</mxpg:PropertyGridControl>
using Eremex.AvaloniaUI.Controls.PropertyGrid;

PropertyGridCategoryRow categoryRowName = new PropertyGridCategoryRow() { Caption = "Name" };
pGrid1.Rows.Add(categoryRowName);
categoryRowName.Rows.Add(new PropertyGridRow() { FieldName = "Caption" });

PropertyGridCategoryRow categoryRowDetails = new PropertyGridCategoryRow() { Caption = "Details" };
pGrid1.Rows.Add(categoryRowDetails);
categoryRowDetails.Rows.Add(new PropertyGridRow() { FieldName = "OrderNo" });
categoryRowDetails.Rows.Add(new PropertyGridRow() { FieldName = "InvoiceNo" });

Создать табуляционных строк

Табуляционная строка (PropertyGridTabRow) позволяет группировать строки в пользовательский интерфейс с вкладками. Он состоит из заголовка, переключателя вкладок и клиентской области. Когда пользователь выбирает вкладку, в клиентской области отображается набор свойств, соответствующий выбранной вкладке. На следующей картинке показан контрол PropertyGrid с двумя табуляционными строками (Appearance и Layout).:

propertygrid-tabrows

Контрол заполняет коллекцию вкладок из дочерних элементов табуляционной строки (объекты PropertyGridTabRowItem). Каждый объект PropertyGridTabRowItem определяет коллекцию строк, связанных с этой вкладкой.

Пример

В следующем примере создается табуляционная строка Appearance, которая состоит из двух вкладок (Text и _Border_1). При выборе каждой вкладки отображается свой собственный набор свойств.

propertygrid-tabrow

xmlns:mxpg="clr-namespace:Eremex.AvaloniaUI.Controls.PropertyGrid;assembly=Eremex.Avalonia.Controls"
xmlns:mxe="clr-namespace:Eremex.AvaloniaUI.Controls.Editors;assembly=Eremex.Avalonia.Controls"

<UserControl.Resources>
    <DataTemplate x:Key="spinEditorTemplate1">
        <mxe:SpinEditor x:Name="PART_Editor" HorizontalContentAlignment="Stretch"/>
    </DataTemplate>
    <DataTemplate x:Key="spinEditorTemplate2">
        <mxe:SpinEditor x:Name="PART_Editor" HorizontalContentAlignment="Stretch" Increment="0.1"/>
    </DataTemplate>
</UserControl.Resources>

<mxpg:PropertyGridControl x:Name="propertyGrid" 
                          SelectedObject="{Binding}" 
                          UseModernAppearance="True" 
                          ImmediatePostEditor="True" 
                          BorderThickness="1,0" Grid.Column="1"
                          ShowSearchPanel="False"
                          >
    <mxpg:PropertyGridRow FieldName="Content"/>

    <mxpg:PropertyGridTabRow Caption="Appearance">
        <mxpg:PropertyGridTabRowItem Header="Text">
            <mxpg:PropertyGridRow FieldName="Foreground"/>
            <mxpg:PropertyGridRow FieldName="FontFamily">
                <mxpg:PropertyGridRow.EditorProperties>
                    <mxe:ComboBoxEditorProperties 
                        IsTextEditable="False" 
                        ItemsSource="{Binding Source={x:Static FontManager.Current}, Path=SystemFonts}" 
                        ValueMember="Name" DisplayMember="Name"/>
                </mxpg:PropertyGridRow.EditorProperties>
            </mxpg:PropertyGridRow>
            <mxpg:PropertyGridRow FieldName="FontSize" CellTemplate="{StaticResource spinEditorTemplate1}"/>

        </mxpg:PropertyGridTabRowItem>

        <mxpg:PropertyGridTabRowItem Header="Border">
            <mxpg:PropertyGridRow FieldName="Background"/>
            <mxpg:PropertyGridRow FieldName="Opacity" CellTemplate="{StaticResource spinEditorTemplate2}"/>
            <mxpg:PropertyGridRow FieldName="BorderThickness" CellTemplate="{StaticResource spinEditorTemplate1}"/>
            <mxpg:PropertyGridRow FieldName="BorderBrush"/>
        </mxpg:PropertyGridTabRowItem>
    </mxpg:PropertyGridTabRow>
</mxpg:PropertyGridControl>

Использование атрибутов для настройки свойств строк

Вы можете применить атрибуты к свойствам привязанного объекта, чтобы настроить статус видимости, свойства просмотра и поведения для соответствующих строк в PropertyGridControl. Поддерживаются следующие атрибуты:

Атрибут Browsable

Атрибут System.ComponentModel.BrowsableAttribute контролирует наличие строк PropertyGrid, которые соответствуют определенным свойствам в привязанном объекте. Чтобы предотвратить создание отдельных строк, примените атрибут Browsable(false) к связанным свойствам.

public partial class MyBusinessObject : ObservableObject
{
    [Browsable(false)]
    public string Caption {
        get;set;
    }
}

Атрибут Category

Атрибут System.ComponentModel.CategoryAttribute задает название категории для свойства. Когда PropertyGrid обнаруживает этот атрибут, примененный к свойству, контрол создает категориальную строку с указанным именем категории и помещает соответствующую строку данных в эту категориальную строку.

[Category("Title")]
public string Caption {
    get;set;
}

Атрибут DisplayName

Атрибут System.ComponentModel.DisplayNameAttribute присваивает свойству пользовательское отображаемое имя. Когда этот атрибут указан, контрол PropertyGrid использует это отображаемое имя для подписей соответствующих строк.

[DisplayName("Name")]
public string Caption {
    get;set;
}

Атрибут Readonly

Атрибут System.ComponentModel.ReadOnlyAttribute помечает свойство как доступное только для чтения и предотвращает операции редактирования соответствующей строки в контроле PropertyGrid.

[ReadOnly(true)]
public string OrderId {
    get; set;
}

Атрибут TypeConverter

Атрибут System.ComponentModel.TypeConverterAttribute позволяет привязать объект TypeConverter (потомок System.ComponentModel.TypeConverter) к свойству.PropertyGrid использует этот конвертер для преобразования отображаемых значений в редактируемые. Функциональность конвертера типов вызывается в следующих случаях:

  • Когда контрол собирается отобразить значение в ячейке или когда изменяется значение редактирования ячейки. TypeConverter преобразует значение редактирования ячейки в отображаемое значение.
  • Когда пользователь редактирует ячейку, а затем перемещает фокус на другую ячейку. TypeConverter выполняет обратное преобразование.

Пользовательские шаблоны строк

Дефолтная отрисовка строки данных состоит из областей заголовка и значений.

Вы можете использовать свойство CellTemplate, чтобы указать шаблон, используемый для отображения областей значений строк. Смотрите следующие разделы для получения дополнительной информации: Редактирование данных и Пользовательские редакторы

Используйте свойство PropertyGridRow.RowTemplate для отображения целых строк (областей заголовка и значений) произвольным способом. Это свойство определяет пользовательский шаблон строки.

Пример - Пользовательский шаблон строк

Следующий код привязывает PropertyGrid к объекту MyBusinessObject, который имеет свойства BorderSize и Location типов Integer и Point соответственно. Код определяет три объекта PropertyGridRow, два из которых используют пользовательские шаблоны. Шаблоны содержат пользовательские контролы для представления и редактирования свойств BorderSize и Location.

propertygrid-rowtemplate-example

Шаблон строки для свойства BorderSize отображает метку, ползунок и SpinEditor. Ползунок и редактор привязаны к целевому свойству BorderSize.

Шаблон строки для редактирования свойства Location содержит две метки и два cde10074. Соответствующий объект PropertyGridRow привязан к свойству Location, в то время как объекты SpinEditor привязаны к вложенным полям X и Y. Альтернативной опцией является использование путей привязки Location.X и Location.Y для редакторов.

xmlns:mxpg="clr-namespace:Eremex.AvaloniaUI.Controls.PropertyGrid;assembly=Eremex.Avalonia.Controls"
xmlns:mxe="clr-namespace:Eremex.AvaloniaUI.Controls.Editors;assembly=Eremex.Avalonia.Controls"

<Window.DataContext>
    <local:SampleViewModel/>
</Window.DataContext>

<mxpg:PropertyGridControl
            x:Name="propertyGrid1" 
            SelectedObject="{Binding Path=MyBusinessObject}"
            UseModernAppearance="True"
            Margin="10"
            BorderThickness="1"
            ShowSearchPanel="False"
            >
            
    <mxpg:PropertyGridCategoryRow Caption="Common">
                
        <mxpg:PropertyGridRow FieldName="Text" />
                
        <mxpg:PropertyGridRow>
            <mxpg:PropertyGridRow.RowTemplate>
                <DataTemplate>
                    <Grid ColumnDefinitions="Auto, 2*, *" Margin="18,5,5,5">
                        <TextBlock Text="Border Size: "  VerticalAlignment="Center" Classes="PropertyGridRow_Modern"/>
                        <Slider Value="{Binding BorderSize, Converter={local:MyDoubleToIntConverter}}" Maximum="500" Focusable="False" Margin="0,0,5,0" Grid.Column="1" />
                        <mxe:SpinEditor EditorValue="{Binding BorderSize}" Maximum="500" Minimum="0" Grid.Column="2" />
                    </Grid>
                </DataTemplate>
            </mxpg:PropertyGridRow.RowTemplate>
        </mxpg:PropertyGridRow>
    </mxpg:PropertyGridCategoryRow>
            
    <mxpg:PropertyGridCategoryRow Caption="Coordinates">
        <mxpg:PropertyGridRow FieldName="Location">
            <mxpg:PropertyGridRow.RowTemplate>
                <DataTemplate>
                    <Grid ColumnDefinitions="*, 20, *"  Margin="18,5,5,5" Grid.Column="0">
						<Grid ColumnDefinitions="Auto, *" >
							<TextBlock Text="X:" HorizontalAlignment="Right" Classes="PropertyGridRow_Modern" VerticalAlignment="Center"/>
							<mxe:SpinEditor EditorValue="{Binding X}" Minimum="0" Maximum="10000" Grid.Column="1" VerticalAlignment="Center"/>
						</Grid>
                        <Grid ColumnDefinitions="Auto, *" Grid.Column="2">
                            <TextBlock Text="Y:" HorizontalAlignment="Right" Classes="PropertyGridRow_Modern" VerticalAlignment="Center"/>
                            <mxe:SpinEditor EditorValue="{Binding Y}" Minimum="0" Maximum="10000" Grid.Column="1" VerticalAlignment="Center"/>
                        </Grid>
                    </Grid>
                </DataTemplate>
            </mxpg:PropertyGridRow.RowTemplate>
        </mxpg:PropertyGridRow>
    </mxpg:PropertyGridCategoryRow>
</mxpg:PropertyGridControl>
using System.Drawing;
using CommunityToolkit.Mvvm.ComponentModel;

public partial class SampleViewModel : ViewModelBase
{
    [ObservableProperty]
    MyBusinessObject myBusinessObject = new MyBusinessObject();
}
public partial class MyBusinessObject : ViewModelBase
{
    [ObservableProperty]
    string text = "Sample text";

    [ObservableProperty]
    double borderSize = 5;

    [ObservableProperty]
    string fontFamily = FontManager.Current.DefaultFontFamily.Name;

    [ObservableProperty]
    double fontSize = 14;

    [ObservableProperty]
    Point location = new Point(11, 22);
}

public class ViewModelBase : ObservableObject
{
}

Генерация строк из коллекции моделей представления строк (MVVM)

PropertyGrid позволяет вам использовать шаблон проектирования MVVM для заполнения контрола строками и инициализации строк из моделей представления.

Следующие свойства PropertyGrid поддерживают шаблон проектирования MVVM:

  • PropertyGridControl.RowsSource — Источник моделей представления строк, которые будут отображаться как корневые строки.
  • PropertyGridCategoryRow.RowsSource — Источник моделей представления строк, которые будут отображаться как дочерние элементы категориальной строки.
  • PropertyGridControl.RowsDataTemplates — Коллекция шаблонов данных, которые определяют объекты PropertyGridRow и PropertyGridCategoryRow, используемые для отображения соответствующих моделей представления строк из коллекций RowsSource.

Пример

В следующем руководстве демонстрируется подход MVVM к заполнению строк. В этом примере инициализируются строки PropertyGrid из View Models и создается пользовательский интерфейс, показанный ниже:

PropertyGrid-RowsDataTemplates-example

В примере создаются категориальные строки Common, Coordinates и Alignment (объекты PropertyGridCategoryRow) из объектов CategoryRowViewModel.

Приведенные ниже модели представления используются для создания обычных строк в категориальных строках:

  • DefaultRowViewModel — ViewModel, соответствующая строке по умолчанию (объект PropertyGridRow с дефолтными настройками). Тип данных значения строки по умолчанию определяет тип встроенного редактора. Объект DefaultRowViewModel используется для создания строк Display Text, Horz Alignment и Vert Alignment.

  • NumericSpinEditorRowViewModel — ViewModel, соответствующая строке PropertyGrid со встроенным SpinEditor. Эта модель представления используется для создания строки Value.

  • PointEditorViewModel — ViewModel, который соответствует строке PropertyGrid с пользовательским шаблоном строки. В этом шаблоне строк отображаются два SpinEditor и две метки, размещенные в линии для представления и редактирования значений типа данных Point.

Шаги:

  1. Определите целевой бизнес-объект, данные которого необходимо отображать/редактировать в PropertyGrid. Привяжите этот объект к контролу с помощью элемента PropertyGridControl.SelectedObject.

    public partial class MyBusinessObject : ViewModelBase
    {
        [ObservableProperty]
        string text = "Sample text";
    
        [ObservableProperty]
        int value = 99;
    
        [ObservableProperty]
        double borderSize = 5;
    
        [property: Category("Font")]
        [ObservableProperty]
        string fontFamily = FontManager.Current.DefaultFontFamily.Name;
    
        [property: Category("Font")]
        [ObservableProperty]
        double fontSize = 14;
    
        [property: Category("Font")]
        [ObservableProperty]
        bool isBold = true;
    
        [property: Category("Font")]
        [ObservableProperty]
        bool isItalic;
    
        [property: Category("Alignment")]
        [ObservableProperty]
        HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center;
    
        [property: Category("Alignment")]
        [ObservableProperty]
        VerticalAlignment verticalAlignment;
    
        [ObservableProperty]
        Point location = new Point(11, 22);
    }
    
    
    xmlns:mxpg="clr-namespace:Eremex.AvaloniaUI.Controls.PropertyGrid;assembly=Eremex.Avalonia.Controls"
    
    <mxpg:PropertyGridControl
        SelectedObject="{Binding MyBusinessObject}"
        ...
        >
        ...
    </mxpg:PropertyGridControl>
    
  2. Создайте классы модели представления строк, содержащие свойства, используемые для инициализации строк PropertyGrid (например, свойства, используемые для инициализации свойств строки PropertyGridRow.FieldName и PropertyGridRow.Caption). Каждая модель представления строк обычно предоставляет уникальный набор свойств и функций. Модель представления для категориальных строк должна предоставлять объект IEnumerable, содержащий дочерние модели представления строк.

    // A View Model that corresponds to regular data rows.
    public class DefaultRowViewModel
    {
        // The path to a target object's property.
        public string? FieldName { get; set; }
    
        // The property's display name.
        public string? Caption { get; set; }
    }
    
    // A View Model that corresponds to category rows.
    public class CategoryRowViewModel
    {
        // The category's display name.
        public string? Caption { get; set; }
    
        // Child row View Models that will be rendered as child rows.
        public IEnumerable? Items { get; set; }
    }
    
    // A View Model that corresponds to a data row with an embedded SpinEditor used to edit numeric values.
    public class NumericSpinEditorRowViewModel
    {
        public string? FieldName { get; set; }
    
        public string? Caption { get; set; }
    
        // The minimum allowed value for the SpinEditor.
        public int? MinValue { get; set; }
        // The maximum allowed value for the SpinEditor.
        public int? MaxValue { get; set; }
    }
    
    // A View Model for a data row that uses two standalone SpinEditors to edit values of the Point data type.
    // This data row will be created from a custom row template.
    public class PointEditorViewModel
    {
        public string? FieldName { get; set; }
    }
    
  3. Создайте объект IEnumerable, который хранит экземпляры модели представления строк в порядке, который PropertyGrid должен использовать для отображения соответствующих строк.

    public partial class SampleViewModel : ViewModelBase
    {
        [ObservableProperty]
        IEnumerable myRowSource = GetMyRowSource();
    
        public static IEnumerable GetMyRowSource()
        {
            return new List<object>
                {
                    new CategoryRowViewModel()
                    {
                        Caption = "Common",
                        Items = new List<object>
                        {
                            new DefaultRowViewModel() { FieldName = "Text", Caption = "Display Text" },
                            new NumericSpinEditorRowViewModel() { FieldName = "Value", Caption = "Value", MinValue=1, MaxValue=100 },
                        }
                    },
    
                    new CategoryRowViewModel()
                    {
                        Caption = "Coordinates",
                        Items = new List<object>
                        {
                            new PointEditorViewModel() { FieldName = "Location" }
                        }
                    },
    
                    new CategoryRowViewModel()
                    {
                        Caption = "Alignment",
                        Items = new List<object>
                        {
                            new DefaultRowViewModel() { FieldName = "HorizontalAlignment", Caption = "Horz Alignment" },
                            new DefaultRowViewModel() { FieldName = "VerticalAlignment", Caption = "Vert Alignment" },
                        }
                    }
                };
        }
    }
    
  4. Установите свойство PropertyGridControl.RowsSource для созданного объекта IEnumerable.

    xmlns:local="using:PropertyGridSample"
    xmlns:mxpg="clr-namespace:Eremex.AvaloniaUI.Controls.PropertyGrid;assembly=Eremex.Avalonia.Controls"
    
    <Window.DataContext>
        <local:SampleViewModel/>
    </Window.DataContext>
    
    
    <mxpg:PropertyGridControl
        SelectedObject="{Binding MyBusinessObject}"
        RowsSource="{Binding MyRowSource}"
        ...
        >
    ...
    </mxpg:PropertyGridControl>
    
  5. Используйте коллекцию PropertyGridControl.RowsDataTemplates для создания шаблонов данных, которые сопоставляют модели представления строк со строками PropertyGrid. Каждый шаблон данных должен определять объект PropertyGridRow или PropertyGridCategoryRow и инициализировать свойства строки, используя информацию, содержащуюся в соответствующей модели представления строк.

    При определении объекта PropertyGridCategoryRow задайте свойству PropertyGridCategoryRow.RowsSource значение источника дочерних моделей представления строк.

    <mxpg:PropertyGridControl
        ...>
        <mxpg:PropertyGridControl.RowsDataTemplates>
            <DataTemplates>
                <DataTemplate DataType="local:CategoryRowViewModel">
                    <mxpg:PropertyGridCategoryRow 
                        Caption="{Binding Path=Caption}"
                        RowsSource="{Binding Path=Items}"/>
                </DataTemplate>
                <DataTemplate DataType="local:DefaultRowViewModel">
                    <mxpg:PropertyGridRow 
                        FieldName="{Binding Path=FieldName}" 
                        Caption="{Binding Path=Caption}"/>
                </DataTemplate>
    
                <DataTemplate DataType="local:NumericSpinEditorRowViewModel">
                    <mxpg:PropertyGridRow FieldName="{Binding Path=FieldName}">
                        <mxpg:PropertyGridRow.EditorProperties >
                            <mxe:SpinEditorProperties 
                                Minimum="{Binding MinValue}" 
                                Maximum="{Binding MaxValue}"/>
                        </mxpg:PropertyGridRow.EditorProperties>
                    </mxpg:PropertyGridRow>
                </DataTemplate>
                <DataTemplate DataType="local:PointEditorViewModel">
                    <mxpg:PropertyGridRow 
                        FieldName="{Binding Path=FieldName}" 
                        RowTemplate="{DynamicResource ResourceKey=pointEditorTemplate}"/>
                </DataTemplate>
            </DataTemplates>
        </mxpg:PropertyGridControl.RowsDataTemplates>
    </mxpg:PropertyGridControl>
    
    СОВЕТ

    Avalonia UI поддерживает иерархический поиск целевых DataTemplates по логическому дереву. Помимо использования свойства RowsDataTemplates, вы можете определить шаблоны в коллекции DataTemplates родительского объекта контрола (parents), объекта Window или объекта Application.

  6. Определите пользовательский шаблон pointEditorTemplate для отображения PropertyGridRow, который соответствует объекту PointEditorViewModel.

    <Window.Resources>
        <DataTemplate x:Key="pointEditorTemplate">
            <Grid ColumnDefinitions="*, 20, *"  Margin="18,5,5,5" Grid.Column="0">
                <Grid ColumnDefinitions="Auto, *" >
                    <TextBlock Text="X:" HorizontalAlignment="Right" Classes="PropertyGridRow_Modern" VerticalAlignment="Center"/>
                    <mxe:SpinEditor EditorValue="{Binding X}" Minimum="0" Maximum="10000" Grid.Column="1" VerticalAlignment="Center"/>
                </Grid>
                <Grid ColumnDefinitions="Auto, *" Grid.Column="2">
                    <TextBlock Text="Y:" HorizontalAlignment="Right" Classes="PropertyGridRow_Modern" VerticalAlignment="Center"/>
                    <mxe:SpinEditor EditorValue="{Binding Y}" Minimum="0" Maximum="10000" Grid.Column="1" VerticalAlignment="Center"/>
                </Grid>
            </Grid>
        </DataTemplate>
    </Window.Resources>
    

Полный код

Ниже вы можете найти полный код руководства.

xmlns:mxpg="clr-namespace:Eremex.AvaloniaUI.Controls.PropertyGrid;assembly=Eremex.Avalonia.Controls"
xmlns:local="using:PropertyGridSample"

<Window.DataContext>
    <local:SampleViewModel/>
</Window.DataContext>

<Window.Resources>
    <DataTemplate x:Key="pointEditorTemplate">
        <Grid ColumnDefinitions="*, 20, *"  Margin="18,5,5,5" Grid.Column="0">
            <Grid ColumnDefinitions="Auto, *" >
                <TextBlock Text="X:" HorizontalAlignment="Right" Classes="PropertyGridRow_Modern" VerticalAlignment="Center"/>
                <mxe:SpinEditor EditorValue="{Binding X}" Minimum="0" Maximum="10000" Grid.Column="1" VerticalAlignment="Center"/>
            </Grid>
            <Grid ColumnDefinitions="Auto, *" Grid.Column="2">
                <TextBlock Text="Y:" HorizontalAlignment="Right" Classes="PropertyGridRow_Modern" VerticalAlignment="Center"/>
                <mxe:SpinEditor EditorValue="{Binding Y}" Minimum="0" Maximum="10000" Grid.Column="1" VerticalAlignment="Center"/>
            </Grid>
        </Grid>
    </DataTemplate>
</Window.Resources>

<mxpg:PropertyGridControl
    Grid.Row="2" Grid.Column="5"
    Background="FloralWhite" BorderThickness="1"
                                  
	SelectedObject="{Binding MyBusinessObject}"
	RowsSource="{Binding MyRowSource}"
	UseModernAppearance="true"
	Margin="10">

<mxpg:PropertyGridControl
    Background="FloralWhite" BorderThickness="1"
	SelectedObject="{Binding MyBusinessObject}"
	RowsSource="{Binding MyRowSource}"
	UseModernAppearance="true"
	Margin="10">

    <mxpg:PropertyGridControl.RowsDataTemplates>
        <DataTemplates>
            <DataTemplate DataType="local:CategoryRowViewModel">
                <mxpg:PropertyGridCategoryRow 
                    Caption="{Binding Path=Caption}"
                    RowsSource="{Binding Path=Items}"/>
            </DataTemplate>
            <DataTemplate DataType="local:DefaultRowViewModel">
                <mxpg:PropertyGridRow 
                    FieldName="{Binding Path=FieldName}" 
                    Caption="{Binding Path=Caption}"/>
            </DataTemplate>

            <DataTemplate DataType="local:NumericSpinEditorRowViewModel">
                <mxpg:PropertyGridRow FieldName="{Binding Path=FieldName}">
                    <mxpg:PropertyGridRow.EditorProperties >
                        <mxe:SpinEditorProperties 
                            Minimum="{Binding MinValue}" 
                            Maximum="{Binding MaxValue}"/>
                    </mxpg:PropertyGridRow.EditorProperties>
                </mxpg:PropertyGridRow>
            </DataTemplate>
            <DataTemplate DataType="local:PointEditorViewModel">
                <mxpg:PropertyGridRow 
                    FieldName="{Binding Path=FieldName}" 
                    RowTemplate="{DynamicResource ResourceKey=pointEditorTemplate}"/>
            </DataTemplate>
        </DataTemplates>
    </mxpg:PropertyGridControl.RowsDataTemplates>
</mxpg:PropertyGridControl>
using Eremex.AvaloniaUI.Controls.Common;
using Avalonia.Layout;
using System.Drawing;
using CommunityToolkit.Mvvm.ComponentModel;

namespace PropertyGridSample;

public partial class SampleViewModel : ViewModelBase
{
    [ObservableProperty]
    IEnumerable myRowSource = GetMyRowSource();

    [ObservableProperty]
    MyBusinessObject myBusinessObject = new MyBusinessObject();

    public static IEnumerable GetMyRowSource()
    {
        return new List<object>
            {
                new CategoryRowViewModel()
                {
                    Caption = "Common",
                    Items = new List<object>
                    {
                        new DefaultRowViewModel() { FieldName = "Text", Caption = "Display Text" },
                        new NumericSpinEditorRowViewModel() { FieldName = "Value", Caption = "Value", MinValue=1, MaxValue=100 },
                    }
                },

                new CategoryRowViewModel()
                {
                    Caption = "Coordinates",
                    Items = new List<object>
                    {
                        new PointEditorViewModel() { FieldName = "Location" }
                    }
                },

                new CategoryRowViewModel()
                {
                    Caption = "Alignment",
                    Items = new List<object>
                    {
                        new DefaultRowViewModel() { FieldName = "HorizontalAlignment", Caption = "Horz Alignment" },
                        new DefaultRowViewModel() { FieldName = "VerticalAlignment", Caption = "Vert Alignment" },
                    }
                }
            };
    }
}

// A View Model that corresponds to regular data rows.
public class DefaultRowViewModel
{
    // The path to a target object's property.
    public string? FieldName { get; set; }

    // The property's display name.
    public string? Caption { get; set; }
}

// A View Model that corresponds to category rows.
public class CategoryRowViewModel
{
    // The category's display name.
    public string? Caption { get; set; }

    // Child row View Models that will be rendered as child rows.
    public IEnumerable? Items { get; set; }
}

// A View Model that corresponds to a data row with an embedded SpinEditor used to edit numeric values.
public class NumericSpinEditorRowViewModel
{
    public string? FieldName { get; set; }

    public string? Caption { get; set; }

    // The minimum allowed value for the SpinEditor.
    public int? MinValue { get; set; }
    // The maximum allowed value for the SpinEditor.
    public int? MaxValue { get; set; }
}

// A View Model for a data row that uses two standalone SpinEditors to edit values of the Point data type.
// This data row will be created from a custom row template.
public class PointEditorViewModel
{
    public string? FieldName { get; set; }
}

public partial class MyBusinessObject : ViewModelBase
{
    [ObservableProperty]
    string text = "Sample text";

    [ObservableProperty]
    int value = 99;

    [ObservableProperty]
    double borderSize = 5;

    [property: Category("Font")]
    [ObservableProperty]
    string fontFamily = FontManager.Current.DefaultFontFamily.Name;

    [property: Category("Font")]
    [ObservableProperty]
    double fontSize = 14;

    [property: Category("Font")]
    [ObservableProperty]
    bool isBold = true;

    [property: Category("Font")]
    [ObservableProperty]
    bool isItalic;

    [property: Category("Alignment")]
    [ObservableProperty]
    HorizontalAlignment horizontalAlignment = HorizontalAlignment.Center;

    [property: Category("Alignment")]
    [ObservableProperty]
    VerticalAlignment verticalAlignment;

    [ObservableProperty]
    Point location = new Point(11, 22);
}


* Эта страница была создана автоматически с помощью сервиса машинного перевода Яндекс Переводчик.