[Программирование, .NET, Промышленное программирование, Xamarin] Эстетика XAML: конвертеры значений
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В статье представлены обобщённые подходы применения конвертеров значений при написании XAML-кода.
IValueConverter Data Binding XAML WPF UWP Xamarin Forms UI SwitchConverter KeyToValueConverter InlineConverter AggregateConverter ResourceDictionary
Конвертеры значений совместно с механизмом привязки данных являются важными компонентами в разработке пользовательских интерфейсов на основе XAML. Конвертеры значений подразумевают наличие логики, помещенной в отдельный класс, реализующий интерфейс IValueConverter. Обычно имя класса отражает функциональное назначение, а сами экземпляры декларируются в разметке.Switch Converter & Key To Value ConverterНа практике многие конвертеры значений имеют тривиальную логику схожую по структуре с тернарным оператором (?:) или конструкциям if-else, switch-case-default. Однако существуют обобщенные шаблоны KeyToValueConverter и SwitchConverter, которые позволяют избежать добавления в проект однотипных по структуре классов путём декларирования логических значений и ветвлений непосредственно в разметке.Концепция
<KeyToValueConverter
Key="KeyForMatching"
Value="ValueIfKeyMatched"
ByDefault="ValueIfKeyNotMatched" />
<SwitchConverter
ByDefault="ValueZ">
<Case
Key="KeyA"
Value="ValueA" />
<Case
Key="KeyB"
Value="ValueB" />
<Case
Key="KeyC"
Value="ValueC" />
</SwitchConverter>
Применение
<KeyToValueConverter
x:Key="TrueToVisibleConverter"
Key="True"
Value="Visible"
ByDefault="Collapsed" />
<ProgressBar
Visibility="{Binding IsBusy, Converter={StaticResource TrueToVisibleConverter}}" />
<SwitchConverter
x:Key="CodeToBackgroundConverter"
ByDefault="White">
<Case
Key="R"
Value="Red" />
<Case
Key="G"
Value="Green" />
<Case
Key="B"
Value="Blue" />
</SwitchConverter>
<Control
Background="{Binding Code, Converter={StaticResource CodeToBackgroundConverter}}" />
KeyToValueConverter - проверяет входное значение на соответствие со значением из свойства Key, если соответствие выполнено, то в качестве выходного берётся значение из свойства Value, в противном случае из свойства ByDefault.SwitchConverter - выполняет поиск первого соответствующего Case из списка по его ключу из свойства Key, если соответствующий Case найден, то берётся заданное в нём значение из свойства ¨C31C, в противном случае из свойства¨C90C¨C32C, заданного в самом конвертере значений.Если свойство Value или ByDefault явно не задано, но выполняется соответствующее ему условие, то в таком случае происходит обыкновенный проброс входного значения в качестве выходного.Также у KeyToValueConverter иногда полезно задавать ключ в ConverterParameter через свойство KeySource
<KeyToValueConverter
x:Key="EqualsToHiddenConverter"
KeySource="ConverterParameter"
Value="Collapsed"
ByDefault="Visible" />
<Control
Visiblity="{Binding Items.Count, ConverterParameter=0, Converter={StaticResource EqualsToHiddenConverter}}" />
<TextBlock
Visiblity="{Binding Text, ConverterParameter='Hide Me', Converter={StaticResource EqualsToHiddenConverter}}" />
Для особых случаев у KeySource возможны четыре режима работы:Manual (by default) - в качестве ключа при проверке соответствия всегда используется значение из свойства Key либо выполняется проброс значения, когда оно не заданоConverterParameter - в качестве ключа всегда используется значение из свойства привязки ConverterParameter либо выполняется проброс значения, когда оно не заданоPreferManual - если manual Key явно задан, то он имеет приоритет перед ConverterParameterPreferConverterParameter - если ConverterParameter явно задан, то он имеет приоритет перед manual KeyСтоит также отметить, что у SwitchConverter помимо обычных Case доступны также TypedCase, основное отличие которых в проверке на соответствие по типу значения
<SwitchConverter
ByDefault="Undefined value">
<TypedCase
Key="system:String"
Value="String value" />
<Case
Key="0"
Value="Zero" />
<Case
Key="1"
Value="One" />
<TypedCase
Key="system:Int32"
Value="Int32 value" />
</SwitchConverter>
Иногда возникает необходимость продебажить работу конвертера значений. Для этой цели у SwitchConverter предусмотрено свойство DiagnosticKey, если оно задано, то при срабатывании привязки данных в Trace будут выводится диагностические сообщения следующего формата
var diagnosticMessage = matchedCase.Is()
? $"{DiagnosticKey}: '{matchedValue}' matched by key '{matchedCase.Key}' for '{value}' and converted to '{convertedValue}'"
: $"{DiagnosticKey}: The default value '{matchedValue}' matched for '{value}' and converted to '{convertedValue}'";
Trace.WriteLine(diagnosticMessage);
<SwitchConverter
DiagnosticKey="UniqDiagnosticKey"
x:Key="CodeToBackgroundConverter"
ByDefault="White">
...
</SwitchConverter>
Dependency Value ConverterТакже свойства Key, Value и ByDefault полезно объявлять в качестве свойств зависимости (Dependency Properties), то есть наследовать конвертеры и Cases от класса DependencyObject. Хотя конвертеры значений обычно не являются элементами визуального дерева, что отчасти ограничивает работу механизма привязки данных, тем не менее остаётся возможность производить привязку к статическим ресурсам или наследникам класса Binding, например
<KeyToValueConverter
Key="AnyKey"
Value="{Binding MatchedValue, Source={StaticResource AnyResource}}"
ByDefault="{Binding DefaultValue, Source={StaticResource AnyResource}}" />
<KeyToValueConverter
Key="AnyKey"
Value="{Localizing MatchedTitle}"
ByDefault="{Localizing DefaultTitle}" />
Inline ConverterВстраиваемый конвертер позволят перенести логику по преобразованию значений из отдельного класса, реализующего интерфейс IValueConverter, в code-behind класс конкретного представления на основе событийной модели.Это позволяет получить доступ к представлению и его отдельным визуальным элементам из логики конвертирования при реализации сложных сценариев, которые затруднительно реализовать при классическом подходе.Для этого необходимо добавить декларацию конвертера в разметку, а code-behind классе определить обработчики для соответствующих событий Converting и ConvertingBack
<Grid>
<Grid.Resources>
<InlineConverter
x:Key="ComplexInlineConverter"
Converting="InlineConverter_OnConverting"
ConvertingBack="InlineConverter_OnConverting" />
</Grid.Resources>
<TextBlock Text="{Binding Number, Converter={StaticResource InlineConverter}}"/>
</Grid>
private void InlineConverter_OnConverting(object sender, ConverterEventArgs e)
{
// e.Value - access to input value
// this.DataContext - access to Data Context or another properties of the view
// access to child visual elements of this root view
e.ConvertedValue = // set output value
$"DataContext: {DataContext}, Converter Value: {e.Value}";
}
private void InlineConverter_OnConvertingBack(object sender, ConverterEventArgs e)
{
// ...
}
Aggregate ConverterАгрегирующий конвертер предназначен для объединения конвертеров в цепочки, при этом преобразование значения происходит последовательно в порядке декларирования вложенных конвертеров.
<AggregateConverter>
<StepAConverter />
<StepBConverter />
<StepCConverter />
</AggregateConverter>
App.xamlОбобщённые конвертеры значений полезно помещать в отдельный Resource Dictionary, а затем мержить их в качестве глобальных ресурсов в файл App.xaml. Это позволяет переиспользовать конвертеры значений в различных представлениях без их повторного декларирования.
<Application
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="Any.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="AppConverters.xaml" />
...
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Ace FrameworkПримеры реализации представленных конвертеров можно найти в библиотеке Ace Framework gitlab bitbucketС благодарностью за внимание и интерес!
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка веб-сайтов, Программирование, IT-инфраструктура, Управление проектами, DevOps] Веб-разработка с нуля: руководство для молодых команд по созданию инфраструктуры CI/CD и процесса разработки
- [Разработка веб-сайтов, JavaScript, Программирование] Заметка о перебираемых объектах
- [Семантика, Программирование, Prolog, Бизнес-модели] Проектируем мульти-парадигменный язык программирования. Часть 3 — Обзор языков представления знаний
- [Промышленное программирование, Разработка робототехники, Программирование микроконтроллеров, Разработка для интернета вещей, Производство и разработка электроники] ModBus Slave RTU/ASCII без смс и регистрации
- [Python, Программирование, Git, GitHub, Учебный процесс в IT] 25 лучших репозиториев GitHub для разработчиков Python (перевод)
- [Разработка веб-сайтов, JavaScript, Программирование] Управление памятью в JavaScript (перевод)
- [Программирование, Kotlin, Управление продуктом] Kotlin: язык программирования как продукт
- [Программирование, Big Data, Машинное обучение] Как я регулярно улучшаю точность моделей обучения с 80% до 90+% (перевод)
- [Программирование, Go] Жизнь в одну строчку (перевод)
- [Программирование, C++, C#] Как подружить .NET и IDA Pro (о дружбе C# и C++)
Теги для поиска: #_programmirovanie (Программирование), #_.net, #_promyshlennoe_programmirovanie (Промышленное программирование), #_xamarin, #_ivalueconverter, #_data_binding, #_xaml, #_wpf, #_uwp, #_xamarin_forms, #_ui, #_switchconverter, #_keytovalueconverter, #_programmirovanie (
Программирование
), #_.net, #_promyshlennoe_programmirovanie (
Промышленное программирование
), #_xamarin
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:45
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В статье представлены обобщённые подходы применения конвертеров значений при написании XAML-кода. IValueConverter Data Binding XAML WPF UWP Xamarin Forms UI SwitchConverter KeyToValueConverter InlineConverter AggregateConverter ResourceDictionary
<KeyToValueConverter
Key="KeyForMatching" Value="ValueIfKeyMatched" ByDefault="ValueIfKeyNotMatched" /> <SwitchConverter ByDefault="ValueZ"> <Case Key="KeyA" Value="ValueA" /> <Case Key="KeyB" Value="ValueB" /> <Case Key="KeyC" Value="ValueC" /> </SwitchConverter> <KeyToValueConverter
x:Key="TrueToVisibleConverter" Key="True" Value="Visible" ByDefault="Collapsed" /> <ProgressBar Visibility="{Binding IsBusy, Converter={StaticResource TrueToVisibleConverter}}" /> <SwitchConverter
x:Key="CodeToBackgroundConverter" ByDefault="White"> <Case Key="R" Value="Red" /> <Case Key="G" Value="Green" /> <Case Key="B" Value="Blue" /> </SwitchConverter> <Control Background="{Binding Code, Converter={StaticResource CodeToBackgroundConverter}}" /> <KeyToValueConverter
x:Key="EqualsToHiddenConverter" KeySource="ConverterParameter" Value="Collapsed" ByDefault="Visible" /> <Control Visiblity="{Binding Items.Count, ConverterParameter=0, Converter={StaticResource EqualsToHiddenConverter}}" /> <TextBlock Visiblity="{Binding Text, ConverterParameter='Hide Me', Converter={StaticResource EqualsToHiddenConverter}}" /> <SwitchConverter
ByDefault="Undefined value"> <TypedCase Key="system:String" Value="String value" /> <Case Key="0" Value="Zero" /> <Case Key="1" Value="One" /> <TypedCase Key="system:Int32" Value="Int32 value" /> </SwitchConverter> var diagnosticMessage = matchedCase.Is()
? $"{DiagnosticKey}: '{matchedValue}' matched by key '{matchedCase.Key}' for '{value}' and converted to '{convertedValue}'" : $"{DiagnosticKey}: The default value '{matchedValue}' matched for '{value}' and converted to '{convertedValue}'"; Trace.WriteLine(diagnosticMessage); <SwitchConverter
DiagnosticKey="UniqDiagnosticKey" x:Key="CodeToBackgroundConverter" ByDefault="White"> ... </SwitchConverter> <KeyToValueConverter
Key="AnyKey" Value="{Binding MatchedValue, Source={StaticResource AnyResource}}" ByDefault="{Binding DefaultValue, Source={StaticResource AnyResource}}" /> <KeyToValueConverter Key="AnyKey" Value="{Localizing MatchedTitle}" ByDefault="{Localizing DefaultTitle}" /> <Grid>
<Grid.Resources> <InlineConverter x:Key="ComplexInlineConverter" Converting="InlineConverter_OnConverting" ConvertingBack="InlineConverter_OnConverting" /> </Grid.Resources> <TextBlock Text="{Binding Number, Converter={StaticResource InlineConverter}}"/> </Grid> private void InlineConverter_OnConverting(object sender, ConverterEventArgs e)
{ // e.Value - access to input value // this.DataContext - access to Data Context or another properties of the view // access to child visual elements of this root view e.ConvertedValue = // set output value $"DataContext: {DataContext}, Converter Value: {e.Value}"; } private void InlineConverter_OnConvertingBack(object sender, ConverterEventArgs e) { // ... } <AggregateConverter>
<StepAConverter /> <StepBConverter /> <StepCConverter /> </AggregateConverter> <Application
xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" x:Class="Any.App"> <Application.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="AppConverters.xaml" /> ... </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Application.Resources> </Application> =========== Источник: habr.com =========== Похожие новости:
Программирование ), #_.net, #_promyshlennoe_programmirovanie ( Промышленное программирование ), #_xamarin |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 18:45
Часовой пояс: UTC + 5