Table of Contents

SegmentedEditor

SegmentedEditor представляет набор элементов (опций) в виде горизонтально расположенных сегментов. Пользователь может щелкнуть по одному из сегментов, чтобы выбрать соответствующую опцию, или нажать CTRL на выбранном сегменте, чтобы отменить выделение.

Основные функции контрола включают в себя:

  • Заполнение сегментов из списка строк, списка бизнес-объектов или из тип-перечисления.
  • Шаблоны элементов позволяют отображать сегменты произвольным способом.
  • Использование контрола в качестве встроенного редактора в контролах-контейнерах (например, TreeList, TreeView и PropertyGrid).

Источник объектов

Используйте свойство SegmentedEditor.ItemsSource, чтобы указать источник объектов, используемый для создания сегментов контрола. Вы можете привязать редактор к списку строк, списку бизнес-объектов или к типу-перечислению.

Привязка к списку строк

Самый простой источник объектов - это список строк.

Пример - Как привязать к списку строк

В следующем примере контрол SegmentedEditor заполняется списком строк.

xmlns:mxe="using:Eremex.AvaloniaUI.Controls.Editors"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:col="using:System.Collections"

<mxe:SegmentedEditor>
    <mxe:SegmentedEditor.ItemsSource>
        <col:ArrayList>
            <sys:String>Montevideo</sys:String>
            <sys:String>Havana</sys:String>
            <sys:String>Santiago</sys:String>
            <sys:String>La Paz</sys:String>
        </col:ArrayList>
    </mxe:SegmentedEditor.ItemsSource>
</mxe:SegmentedEditor>

Привязка к списку бизнес-объектов

Вы можете привязать контрол SegmentedEditor к списку бизнес-объектов. В этом случае дефолтное поведение контрола является следующим:

  • Метод ToString бизнес-объекта задает дефолтное представление текста элементов.
  • Когда вы выбираете элемент, значение редактора (SegmentedEditor.EditorValue) устанавливается равным соответствующему бизнес-объекту.

Типичный бизнес-объект обладает множеством свойств. Вы можете указать, какие свойства бизнес-объекта предоставляют текст элемента для отображения и редактирования значений. Для этой цели используйте следующие элементы API:

  • SegmentedEditor.DisplayMember - Получает или задает имя свойства бизнес-объекта, которое определяет текст элемента для отображения.
  • SegmentedEditor.ValueMember - Получает или задает имя свойства бизнес-объекта, которое определяет значения элемента. Когда вы выбираете элемент, значение редактора (SegmentedEditor.EditorValue) устанавливается равным значению свойства ValueMember элемента.

Пример - Как привязать к списку бизнес-объектов

Следующий пример привязывает контрол SegmentedEditor к списку бизнес-объектов Product. Свойство Product.ProductName определяет текст элемента для отображения. Свойство Product.ProductID определяет значения элементов.

xmlns:mxe="using:Eremex.AvaloniaUI.Controls.Editors"
xmlns:sys="clr-namespace:System;assembly=mscorlib"

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

<mxe:SegmentedEditor
    Name="segmEditor1"
    ItemsSource="{Binding Products}"
    DisplayMember="ProductName"
    ValueMember="ProductID" />
public MainViewModel()
{
    Products = new ObservableCollection<Product>();
    Products.Add(new Product(0, "Chai", "Beverages", 200));
    Products.Add(new Product(1, "Chang", "Beverages", 100))
    Products.Add(new Product(3, "Ikura", "Seafood", 500));
    Products.Add(new Product(5, "Tofu", "Produce", 430));
    //...
}

public partial class Product :ObservableObject
{
    public Product(int productID, string productName, string category, int productPrice)
    {
        ProductID = productID;
        ProductName = productName;
        Category = category;
        ProductPrice = productPrice;
    }

    [ObservableProperty]
    public int productID;

    [ObservableProperty]
    public string productName;

    [ObservableProperty]
    public string category;

    [ObservableProperty]
    public decimal productPrice;
}

Привязка к перечислению

SegmentedEditor может заполнять свои сегменты значениями с тип-перечислением.

Вспомогательный класс Eremex.AvaloniaUI.Controls.Common.EnumItemsSource облегчает привязку к перечислению. Его основные функции включают:

  • Картинки для элементов перечисления. Примените атрибут Eremex.AvaloniaUI.Controls.Common.ImageAttribute к целевым элементам перечисления, чтобы указать картинки.
  • Пользовательские отображаемые имена для элементов перечисления. Используйте атрибут System.ComponentModel.DataAnnotations.DisplayAttribute или пользовательский конвертер, чтобы изменить дефолтный отображаемый текст элемента.
  • Всплывающие подсказки для элементов. Всплывающая подсказка содержит описание целевого элемента, которое вы можете предоставить с помощью атрибута System.ComponentModel.DataAnnotations.DisplayAttribute или пользовательского конвертера.

Чтобы настроить привязку к типу-перечислению, используйте следующие свойства EnumItemsSource:

  • EnumItemsSource.EnumType — Задает тип-перечисление, значения которого отображаются в контроле SegmentedEditor.
  • EnumItemsSource.ShowImages — Указывает, следует ли отображать картинки для элементов перечисления. Вы можете предоставить картинки, используя атрибут Eremex.AvaloniaUI.Controls.Common.ImageAttribute.
  • EnumItemsSource.ShowNames — Указывает, следует ли отображать текст элемента. Установите для ShowNames значение false, а для ShowImages значение true, чтобы отображать элементы перечисления с использованием картинок без текста.
  • EnumItemsSource.ImageSize — Определяет размер отображения картинок, назначенных элементам перечисления.
  • EnumItemsSource.NameToDisplayTextConverter — Позволяет назначить конвертер, который извлекает пользовательский текст для отображения для элементов перечисления.
  • EnumItemsSource.NameToDescriptionConverter — Позволяет назначить конвертер, который извлекает описания элементов перечисления, которые отображаются в виде всплывающих подсказок, когда пользователь наводит курсор мыши на сегменты.

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

В следующем примере отображаются значения перечисления ProductCategoryEnum в SegmentedEditor. В нем используется класс EnumItemsSource для привязки данных.

Атрибуты System.ComponentModel.DataAnnotations.DisplayAttribute и Eremex.AvaloniaUI.Controls.Common.ImageAttribute определяют пользовательский текст для отображения, описания (всплывающие подсказки) и картинки для элементов перечисления.

xmlns:mxcom="clr-namespace:Eremex.AvaloniaUI.Controls.Common;assembly=Eremex.Avalonia.Controls"
xmlns:mxe="using:Eremex.AvaloniaUI.Controls.Editors"

<mxe:SegmentedEditor Name="segmentedEditorEnum"
		ItemsSource="{mxcom:EnumItemsSource EnumType=local:ProductCategoryEnum, ImageSize='16, 16', ShowImages=True, ShowNames=True}"
		>
</mxe:SegmentedEditor>
using Eremex.AvaloniaUI.Controls.Common;
using System.ComponentModel.DataAnnotations;

public enum ProductCategoryEnum
{
    // The images assigned to the enumeration values below are placed in the EditorsSample/Images folder.
    // They have their "Build Action" properties set to "AvaloniaResource".
    [Image($"avares://EditorsSample/Images/Products/DairyProducts.svg")]
    [Display(Name = "Dairy Products", Description = "Products made from milk")]
    DairyProducts,

    [Image($"avares://EditorsSample/Images/Products/Beverages.svg")]
    [Display(Description = "Edible drinks")]
    Beverages,

    [Image($"avares://EditorsSample/Images/Products/Condiments.svg")]
    [Display(Description = "Flavor Enhancers")]
    Condiments,

    [Image($"avares://EditorsSample/Images/Products/Confections.svg")]
    [Display(Description = "Sweets")]
    Confections
}

Пример - Как отобразить значения перечисления и использовать пользовательские конвертеры для предоставления текста для элементов перечисления.

В следующем примере для отображения значений типа-перечисления в контроле SegmentedEditor используется класс EnumItemsSource. Объекты EnumItemsSource.NameToDisplayTextConverter и EnumItemsSource.NameToDescriptionConverter предоставляют пользовательский текст для отображения и описания (всплывающие подсказки) для элементов перечисления.

xmlns:mxe="using:Eremex.AvaloniaUI.Controls.Editors"
xmlns:mxcom="clr-namespace:Eremex.AvaloniaUI.Controls.Common;assembly=Eremex.Avalonia.Controls"
xmlns:local="clr-namespace:EditorsSample"

<mxe:SegmentedEditor Name="segmentedEditorEnumWithConverters"
		ItemsSource="{mxcom:EnumItemsSource EnumType=local:ProductCategoryEnum, ImageSize='16, 16', ShowImages=True, ShowNames=True, NameToDisplayTextConverter={local:EnumMemberNameToDisplayTextConverter}, NameToDescriptionConverter={local:EnumMemberNameToDescriptionConverter}}"
		>
</mxe:SegmentedEditor>
using Eremex.AvaloniaUI.Controls.Common;

public enum ProductCategoryEnum
{
    // The images assigned to the enumeration values below are placed in the EditorsSample/Images folder.
    // They have their "Build Action" properties set to "AvaloniaResource".
    [Image($"avares://EditorsSample/Images/Products/DairyProducts.svg")]
    DairyProducts,

    [Image($"avares://EditorsSample/Images/Products/Beverages.svg")]
    Beverages,

    [Image($"avares://EditorsSample/Images/Products/Condiments.svg")]
    Condiments,

    [Image($"avares://EditorsSample/Images/Products/Confections.svg")]
    Confections
}


public class EnumMemberNameToDisplayTextConverter : BaseEnumConverter
{
    protected override void PopulateDictionary()
    {
        TextValueDictionary.Add("ProductCategoryEnum_DairyProducts", "Dairy");
    }
}
public class EnumMemberNameToDescriptionConverter : BaseEnumConverter
{
    protected override void PopulateDictionary()
    {
        TextValueDictionary.Add("ProductCategoryEnum_DairyProducts", "Milk Products");
    }
}

public abstract class BaseEnumConverter : MarkupExtension, IValueConverter
{
    protected Dictionary<string, string> TextValueDictionary;

    public BaseEnumConverter()
    {
        TextValueDictionary = new Dictionary<string, string>();
        PopulateDictionary();
    }

    protected abstract void PopulateDictionary();

    public override object ProvideValue(IServiceProvider serviceProvider)
    {
        return this;
    }
    public object? Convert(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture)
    {
        var type = value?.GetType();
        var memberName = value?.ToString();
        if (type == null || !type.IsEnum || string.IsNullOrEmpty(memberName))
            return null;
        return EnumMemberToString(type.Name, memberName);
    }
        
    protected virtual string EnumMemberToString(string enumName, string enumMemberName)
    {
        string fullMemberName = enumName + "_" + enumMemberName;
        if (TextValueDictionary.ContainsKey(fullMemberName))
            return TextValueDictionary[fullMemberName];
        else 
            return enumMemberName;
    }
        
    public object? ConvertBack(object? value, Type targetType, object? parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

Получение и установка выбранного элемента, а также выставление значения редактора

Когда пользователь выбирает сегмент или отменяет его выбор щелчком мыши с Ctrl, свойства SegmentedEditor.SelectedItem и SegmentedEditor.EditorValue изменяются соответствующим образом. Вы можете использовать любое из этих свойств, чтобы получить и установить выбранное значение редактора.

Свойство SegmentedEditor.SelectedItem определяет нижележащий объект данных выбранного сегмента.

Свойство SegmentedEditor.EditorValue имеет следующие значения:

  • Если свойство ValueMember пусто, то свойства EditorValue и SelectedItem эквивалентны.
  • В противном случае свойство EditorValue синхронизируется со значением свойства ValueMember выбранного нижележащего объекта данных.

Чтобы снять выделение, установите для свойства SegmentedEditor.SelectedItem значение null.

Пример - Как выбрать элемент, когда SegmentedEditor привязан к списку строк

В следующем примере показано, как использовать свойство SelectedItem или EditorValue для выбора элемента в контроле SegmentedEditor, который привязан к списку строк.

xmlns:mxe="using:Eremex.AvaloniaUI.Controls.Editors"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:col="using:System.Collections"

<mxe:SegmentedEditor Name="segmEditorStrings">
    <mxe:SegmentedEditor.ItemsSource>
        <col:ArrayList>
            <sys:String>Montevideo</sys:String>
            <sys:String>Havana</sys:String>
            <sys:String>Santiago</sys:String>
            <sys:String>La Paz</sys:String>
        </col:ArrayList>
    </mxe:SegmentedEditor.ItemsSource>
</mxe:SegmentedEditor>
// Use the SelectedItem property:
segmEditorStrings.SelectedItem = "Santiago";
//or the EditorValue property:
segmEditorStrings.EditorValue = "Santiago";

Пример - Как выбрать элемент, когда SegmentedEditor привязан к списку бизнес-объектов

В следующем примере контрол SegmentedEditor привязан к списку объектов Product. Свойство ValueMember ссылается на элемент Product.ProductID. Таким образом, идентификаторы продуктов служат значениями элементов. Когда пользователь выбирает сегмент, свойству EditorValue присваивается соответствующий идентификатор продукта. В примере используется свойство EditorValue для выбора элемента в коде.

xmlns:mxe="using:Eremex.AvaloniaUI.Controls.Editors"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
xmlns:local="clr-namespace:EditorsSample"

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

<mxe:SegmentedEditor
    Name="segmEditor1"
    ItemsSource="{Binding Products}"
    DisplayMember="ProductName"
    ValueMember="ProductID" />
// Select an item by its product ID:
var itemSource = segmEditor1.ItemsSource as ObservableCollection<Product>;
if (itemSource != null)
    segmEditor1.EditorValue = itemSource[3].ProductID;
//The SelectedItem property will return the itemSource[3] object.

//...
[ObservableObject]
public partial class MainViewModel : ViewModelBase
{
    [ObservableProperty]
    public ObservableCollection<Product> products;

    public MainViewModel()
    {
        Products = new ObservableCollection<Product>();
        Products.Add(new Product(0, "Chai", "Beverages", 200));
        Products.Add(new Product(1, "Chang", "Beverages", 100))
        Products.Add(new Product(3, "Ikura", "Seafood", 500));
        Products.Add(new Product(5, "Tofu", "Produce", 430));
    }
}

public partial class Product :ObservableObject
{
    public Product(int productID, string productName, string category, int productPrice)
    {
        ProductID = productID;
        ProductName = productName;
        Category = category;
        ProductPrice = productPrice;
    }

    [ObservableProperty]
    public int productID;

    [ObservableProperty]
    public string productName;

    [ObservableProperty]
    public string category;

    [ObservableProperty]
    public decimal productPrice;
}

Шаблоны элементов

Когда SegmentedEditor привязан к списку строк или бизнес-объектов, сегменты контрола отображают дефолтное представление текста элементов. Дефолтный отображаемый текст элемента определяется следующим образом:

  • Значение, возвращаемое методом ToString нижележащего объекта данных, если свойство ValueMember не задано.
  • В противном случае используется текстовое представление значения, хранящегося в свойстве ValueMember объекта данных.

Шаблоны элементов дают вам возможность гибко указывать, что отображать в сегментах редактора. Они позволяют отображать картинки и значения нескольких свойств в сегментах. Используйте свойство SegmentedEditor.ItemTemplate, чтобы указать шаблон элемента.

Пример - Как отобразить картинку и текст для элементов SegmentedEditor

В следующем примере показано, как создать шаблон элемента, который отображает картинки и текст в сегментах контрола SegmentedEditor.

В примере контрол SegmentedEditor привязан к коллекции объектов CapitalInfo, которые хранят информацию о странах, столицах стран и национальных флагах. Созданный шаблон элемента (свойство SegmentedEditor.ItemTemplate) отображает флаг страны, за которым следует название столицы страны.

Свойство SegmentedEditor.ValueMember ссылается на свойство CapitalInfo.Capital. Когда пользователь выбирает сегмент, свойству редактора EditorValue присваивается название столицы соответствующей страны.

xmlns:mxe="using:Eremex.AvaloniaUI.Controls.Editors"
xmlns:local="clr-namespace:EditorsSample"

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

<Window.Resources>
    <DataTemplate x:Key="CapitalItemTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Image Width="16" Height="16" Source="{Binding Path=Flag}"/>
            <TextBlock VerticalAlignment="Center" Grid.Column="1" Margin="6,0,0,0" Text="{Binding Path=Capital}"/>
        </Grid>
    </DataTemplate>
</Window.Resources>

<mxe:SegmentedEditor
    Name="segmentedEditorCapitals"
    ItemsSource="{Binding Capitals}"
    ItemTemplate="{StaticResource CapitalItemTemplate}"
    ValueMember="Capital"
/>
using CommunityToolkit.Mvvm.ComponentModel;
using Avalonia.Media;
using Avalonia.Svg.Skia;

public partial class MainViewModel 
{
    [ObservableProperty]
    public ObservableCollection<CapitalInfo> capitals;

    public MainViewModel()
    {
        var capitalDictionary = new List<(string capital, string country)>();
        capitalDictionary.Add(("Havana", "Cuba"));
        capitalDictionary.Add(("Santiago", "Chile"));
        capitalDictionary.Add(("La Paz", "Bolivia"));
        Capitals = new ObservableCollection<CapitalInfo>();
        foreach (var item in capitalDictionary)
        {
            string country = item.country.ToLower();
            // Load .SVG images that are stored in the Images/Flags folder as Avalonia Resources.
            IImage image = SvgImageExtension.ProvideValue($"avares://EditorsSample/Images/Flags/{country}.svg", null!, null!);
            Capitals.Add(new CapitalInfo(item.capital, item.country, image));
        }
    }
}

public partial class CapitalInfo : ObservableObject
{
    public CapitalInfo(string capital, string country, IImage flag)
    {
        Capital = capital;
        Flag = flag;
        Country = country;
    }

    [ObservableProperty]
    public string capital;

    [ObservableProperty]
    public string country;

    [ObservableProperty]
    public IImage flag;
}


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