{"id":413442,"date":"2024-06-29T23:07:39","date_gmt":"2024-06-29T23:07:39","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=413442"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=413442","title":{"rendered":"<span>XAML Aesthetics: Value Converters<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>This article presents generalized approaches for using <code>value converters<\/code> into writing of <code>XAML<\/code> code.<\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/526450\/\" rel=\"noopener noreferrer nofollow\">>> Read in Russian<\/a><\/p>\n<figure class=\"float bordered full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w780q1\/getpro\/habr\/upload_files\/2d2\/a5f\/a90\/2d2a5fa901e8e755ca8601ffe062b32b.jpg\" width=\"640\" height=\"362\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/2d2\/a5f\/a90\/2d2a5fa901e8e755ca8601ffe062b32b.jpg\" data-blurred=\"true\"\/><figcaption><\/figcaption><\/figure>\n<blockquote>\n<p><code>IValueConverter<\/code> <code>Data Binding<\/code> <code>XAML<\/code> <code>WPF<\/code> <code>UWP<\/code> <code>Xamarin Forms<\/code> <code>UI<\/code> <code>SwitchConverter<\/code> <code>KeyToValueConverter<\/code> <code>InlineConverter<\/code> <code>AggregateConverter<\/code> <code>ResourceDictionary<\/code><\/p>\n<\/blockquote>\n<p><code>Value converters<\/code> together with a data binding mechanism are essential components into XAML-based development of user interfaces. Value converters imply the presence of logic placed in a separated class that implements the <code>IValueConverter<\/code> interface. Typically, the class name reflects the functional purpose, and the instances are declared in the markup.<\/p>\n<p><strong>Switch Converter &amp; Key To Value Converter<\/strong><\/p>\n<p>At practice many value converters have trivial logic similar by structure with <code>ternary operator (? :)<\/code> or <code>if-else<\/code>, <code>switch-case-default<\/code> constructions. However, there are generalized patterns <code>KeyToValueConverter<\/code> and <code>SwitchConverter<\/code>, which allow to avoid adding to the project of similar by structure classes via declaring logical values and branches directly into markup.<\/p>\n<p><strong><em>Conception<\/em><\/strong><\/p>\n<pre><code class=\"xml\">&lt;KeyToValueConverter Key=\"KeyForMatching\" Value=\"ValueIfKeyMatched\" ByDefault=\"ValueIfKeyNotMatched\" \/>  &lt;SwitchConverter ByDefault=\"ValueZ\"> &lt;Case Key=\"KeyA\" Value=\"ValueA\" \/> &lt;Case Key=\"KeyB\" Value=\"ValueB\" \/> &lt;Case Key=\"KeyC\" Value=\"ValueC\" \/> &lt;\/SwitchConverter><\/code><\/pre>\n<p><strong><em>Usage<\/em><\/strong> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<pre><code class=\"xml\">&lt;KeyToValueConverter x:Key=\"TrueToVisibleConverter\" Key=\"True\" Value=\"Visible\" ByDefault=\"Collapsed\" \/>  &lt;ProgressBar Visibility=\"{Binding IsBusy, Converter={StaticResource TrueToVisibleConverter}}\" \/><\/code><\/pre>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<pre><code class=\"xml\">&lt;SwitchConverter x:Key=\"CodeToBackgroundConverter\" ByDefault=\"White\"> &lt;Case Key=\"R\" Value=\"Red\" \/> &lt;Case Key=\"G\" Value=\"Green\" \/> &lt;Case Key=\"B\" Value=\"Blue\" \/> &lt;\/SwitchConverter>  &lt;Control Background=\"{Binding Code, Converter={StaticResource CodeToBackgroundConverter}}\" \/><\/code><\/pre>\n<p><code>KeyToValueConverter<\/code> &#8212; checks the input value for compliance with the value from the <code>Key<\/code> property, if the match is met, then the value from the <code>Value<\/code> property is taken as the output, otherwise from the <code>ByDefault<\/code> property.<\/p>\n<p><code>SwitchConverter<\/code> &#8212; searches for the first matching <code>Case<\/code> from the list by its key from the <code>Key<\/code> property, if the corresponding <code>Case<\/code> is found, then the value specified in it from the <code>Value<\/code> property is taken, otherwise from the <code>ByDefault<\/code> property, specified in the converter itself.<\/p>\n<p>If the property <code>Value<\/code> or<code>ByDefault<\/code> is not explicitly set, but the corresponding condition is satisfied, then in this case, an ordinary forwarding of the input value as an output occurs.<\/p>\n<p>Also, it is sometimes useful for <code>KeyToValueConverter<\/code> to set a key in <code>ConverterParameter<\/code> via the <code>KeySource<\/code> property<\/p>\n<pre><code class=\"xml\">&lt;KeyToValueConverter x:Key=\"EqualsToHiddenConverter\" KeySource=\"ConverterParameter\" Value=\"Collapsed\" ByDefault=\"Visible\" \/>  &lt;Control Visiblity=\"{Binding Items.Count, ConverterParameter=0, Converter={StaticResource EqualsToHiddenConverter}}\" \/>  &lt;TextBlock Visiblity=\"{Binding Text, ConverterParameter='Hide Me', Converter={StaticResource EqualsToHiddenConverter}}\" \/><\/code><\/pre>\n<p>There are four work modes of <code>KeySource<\/code> for special cases:\u00a0<\/p>\n<p><code>Manual<\/code> (<code>by default<\/code>) &#8212;\u00a0\u00a0the value from the <code>Key<\/code> property is always used as a key during matching, or the value is forwarded when it is not set<\/p>\n<p><code>ConverterParameter<\/code> &#8212;\u00a0\u00a0the value from the binding&#8217;s property <code>ConverterParameter<\/code> is always used as the key during matching, or the value is passed through when it is not set<\/p>\n<p><code>PreferManual<\/code> &#8212; if <code>manual Key<\/code> is explicitly set, it takes precedence over <code>ConverterParameter<\/code><\/p>\n<p><code>PreferConverterParameter<\/code> &#8212; if <code>ConverterParameter<\/code> is explicitly set, then it takes precedence over manual <code>Key<\/code><\/p>\n<p>Note that <code>SwitchConverter<\/code>, in addition to the usual <code>Case<\/code>, also has <code>TypedCase<\/code>, the main difference of which is matching by value type<\/p>\n<pre><code class=\"xml\">&lt;SwitchConverter ByDefault=\"Undefined value\"> &lt;TypedCase Key=\"system:String\" Value=\"String value\" \/> &lt;Case Key=\"0\" Value=\"Zero\" \/> &lt;Case Key=\"1\" Value=\"One\" \/> &lt;TypedCase Key=\"system:Int32\" Value=\"Int32 value\" \/> &lt;\/SwitchConverter><\/code><\/pre>\n<p>Sometimes it becomes necessary to debug the value converter. For this purpose, <code>SwitchConverter<\/code> has a <code>DiagnosticKey<\/code> property, if it is been set, then when the data binding is been triggered, diagnostic messages of the following format will be displayed in <code>Trace<\/code><\/p>\n<pre><code class=\"cs\">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);<\/code><\/pre>\n<pre><code class=\"xml\">&lt;SwitchConverter DiagnosticKey=\"UniqDiagnosticKey\" x:Key=\"CodeToBackgroundConverter\" ByDefault=\"White\"> ... &lt;\/SwitchConverter><\/code><\/pre>\n<p><strong>Dependency Value Converter<\/strong><\/p>\n<p>It is also useful to declare <code>Key<\/code>, <code>Value<\/code> and <code>ByDefault<\/code> properties as <code>Dependency Properties<\/code>, that means inheritance of converters and <code>Case<\/code>s from the <code>DependencyObject<\/code> class. Although value converters are usually not elements of the visual tree, which partly limits the work of the data binding mechanism, nevertheless, it remains possible to bind to static resources or descendants of the <code>Binding<\/code> class, for example<\/p>\n<pre><code class=\"xml\">&lt;KeyToValueConverter Key=\"AnyKey\" Value=\"{Binding MatchedValue, Source={StaticResource AnyResource}}\" ByDefault=\"{Binding DefaultValue, Source={StaticResource AnyResource}}\" \/>  &lt;KeyToValueConverter Key=\"AnyKey\" Value=\"{Localizing MatchedTitle}\" ByDefault=\"{Localizing DefaultTitle}\" \/><\/code><\/pre>\n<p><strong>Inline Converter<\/strong><\/p>\n<p><code>Inline Converter<\/code> allow to transfer the values conversion logic \u200b\u200bfrom a separate class that implements the <code>IValueConverter<\/code> interface into the <code>code-behind<\/code> class of a concrete view based on the event model.<\/p>\n<p>This allows to access the view and its individual visual elements from the conversion logic during implementation of complex scenarios that are difficult to implement with the classical approach.<\/p>\n<p>To do this, you need to add the converter declaration to the markup, and into the <code>code-behind<\/code> class define handlers for the corresponding <code>Converting<\/code> and <code>ConvertingBack<\/code> events<\/p>\n<pre><code class=\"xml\">&lt;Grid> &lt;Grid.Resources> &lt;InlineConverter x:Key=\"ComplexInlineConverter\" Converting=\"InlineConverter_OnConverting\" ConvertingBack=\"InlineConverter_OnConverting\" \/> &lt;\/Grid.Resources>  &lt;TextBlock Text=\"{Binding Number, Converter={StaticResource InlineConverter}}\" \/> &lt;\/Grid><\/code><\/pre>\n<pre><code class=\"cs\">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) { \/\/ ... }<\/code><\/pre>\n<p><strong>Aggregate Converter<\/strong><\/p>\n<p>Aggregate converter intends for combining converters into chains, while the value is converted sequentially in the order in which nested converters are declared.<\/p>\n<pre><code class=\"xml\">&lt;AggregateConverter> &lt;StepAConverter \/> &lt;StepBConverter \/> &lt;StepCConverter \/> &lt;\/AggregateConverter><\/code><\/pre>\n<p><strong>App.xaml<\/strong><\/p>\n<p>It is useful to locate generic value converters in a separate Resource Dictionary and then merge them as global resources into the App.xaml file. This allows to reuse value converters in different views without re-declaring them.<\/p>\n<pre><code class=\"xml\">&lt;Application xmlns=\"http:\/\/xamarin.com\/schemas\/2014\/forms\" xmlns:x=\"http:\/\/schemas.microsoft.com\/winfx\/2009\/xaml\" x:Class=\"Any.App\"> &lt;Application.Resources> &lt;ResourceDictionary> &lt;ResourceDictionary.MergedDictionaries> &lt;ResourceDictionary Source=\"AppConverters.xaml\" \/> ... &lt;\/ResourceDictionary.MergedDictionaries> &lt;\/ResourceDictionary> &lt;\/Application.Resources> &lt;\/Application><\/code><\/pre>\n<p><strong>Ace Framework<\/strong><\/p>\n<p>Examples of implementation of the presented converters can be found into the <code>Ace Framework<\/code> library <a href=\"https:\/\/gitlab.com\/Makeloft-Studio\/Ace\/-\/tree\/master\/Ace.Zest\/Converters\" rel=\"noopener noreferrer nofollow\">gitlab<\/a> <a href=\"https:\/\/bitbucket.org\/Makeloft\/ace\/src\/master\/Ace.Zest\/Converters\/\" rel=\"noopener noreferrer nofollow\">bitbucket<\/a><\/p>\n<p>With gratitude for your attention and interest!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/526480\/\"> https:\/\/habr.com\/ru\/articles\/526480\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>This article presents generalized approaches for using <code>value converters<\/code> into writing of <code>XAML<\/code> code.<\/p>\n<p><a href=\"https:\/\/habr.com\/ru\/post\/526450\/\" rel=\"noopener noreferrer nofollow\">>> Read in Russian<\/a><\/p>\n<figure class=\"float bordered full-width\"><figcaption><\/figcaption><\/figure>\n<blockquote>\n<p><code>IValueConverter<\/code> <code>Data Binding<\/code> <code>XAML<\/code> <code>WPF<\/code> <code>UWP<\/code> <code>Xamarin Forms<\/code> <code>UI<\/code> <code>SwitchConverter<\/code> <code>KeyToValueConverter<\/code> <code>InlineConverter<\/code> <code>AggregateConverter<\/code> <code>ResourceDictionary<\/code><\/p>\n<\/blockquote>\n<p><code>Value converters<\/code> together with a data binding mechanism are essential components into XAML-based development of user interfaces. Value converters imply the presence of logic placed in a separated class that implements the <code>IValueConverter<\/code> interface. Typically, the class name reflects the functional purpose, and the instances are declared in the markup.<\/p>\n<p><strong>Switch Converter &amp; Key To Value Converter<\/strong><\/p>\n<p>At practice many value converters have trivial logic similar by structure with <code>ternary operator (? :)<\/code> or <code>if-else<\/code>, <code>switch-case-default<\/code> constructions. However, there are generalized patterns <code>KeyToValueConverter<\/code> and <code>SwitchConverter<\/code>, which allow to avoid adding to the project of similar by structure classes via declaring logical values and branches directly into markup.<\/p>\n<p><strong><em>Conception<\/em><\/strong><\/p>\n<pre><code class=\"xml\">&lt;KeyToValueConverter Key=\"KeyForMatching\" Value=\"ValueIfKeyMatched\" ByDefault=\"ValueIfKeyNotMatched\" \/>  &lt;SwitchConverter ByDefault=\"ValueZ\"> &lt;Case Key=\"KeyA\" Value=\"ValueA\" \/> &lt;Case Key=\"KeyB\" Value=\"ValueB\" \/> &lt;Case Key=\"KeyC\" Value=\"ValueC\" \/> &lt;\/SwitchConverter><\/code><\/pre>\n<p><strong><em>Usage<\/em><\/strong> \u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<pre><code class=\"xml\">&lt;KeyToValueConverter x:Key=\"TrueToVisibleConverter\" Key=\"True\" Value=\"Visible\" ByDefault=\"Collapsed\" \/>  &lt;ProgressBar Visibility=\"{Binding IsBusy, Converter={StaticResource TrueToVisibleConverter}}\" \/><\/code><\/pre>\n<p>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<\/p>\n<pre><code class=\"xml\">&lt;SwitchConverter x:Key=\"CodeToBackgroundConverter\" ByDefault=\"White\"> &lt;Case Key=\"R\" Value=\"Red\" \/> &lt;Case Key=\"G\" Value=\"Green\" \/> &lt;Case Key=\"B\" Value=\"Blue\" \/> &lt;\/SwitchConverter>  &lt;Control Background=\"{Binding Code, Converter={StaticResource CodeToBackgroundConverter}}\" \/><\/code><\/pre>\n<p><code>KeyToValueConverter<\/code> &#8212; checks the input value for compliance with the value from the <code>Key<\/code> property, if the match is met, then the value from the <code>Value<\/code> property is taken as the output, otherwise from the <code>ByDefault<\/code> property.<\/p>\n<p><code>SwitchConverter<\/code> &#8212; searches for the first matching <code>Case<\/code> from the list by its key from the <code>Key<\/code> property, if the corresponding <code>Case<\/code> is found, then the value specified in it from the <code>Value<\/code> property is taken, otherwise from the <code>ByDefault<\/code> property, specified in the converter itself.<\/p>\n<p>If the property <code>Value<\/code> or<code>ByDefault<\/code> is not explicitly set, but the corresponding condition is satisfied, then in this case, an ordinary forwarding of the input value as an output occurs.<\/p>\n<p>Also, it is sometimes useful for <code>KeyToValueConverter<\/code> to set a key in <code>ConverterParameter<\/code> via the <code>KeySource<\/code> property<\/p>\n<pre><code class=\"xml\">&lt;KeyToValueConverter x:Key=\"EqualsToHiddenConverter\" KeySource=\"ConverterParameter\" Value=\"Collapsed\" ByDefault=\"Visible\" \/>  &lt;Control Visiblity=\"{Binding Items.Count, ConverterParameter=0, Converter={StaticResource EqualsToHiddenConverter}}\" \/>  &lt;TextBlock Visiblity=\"{Binding Text, ConverterParameter='Hide Me', Converter={StaticResource EqualsToHiddenConverter}}\" \/><\/code><\/pre>\n<p>There are four work modes of <code>KeySource<\/code> for special cases:\u00a0<\/p>\n<p><code>Manual<\/code> (<code>by default<\/code>) &#8212;\u00a0\u00a0the value from the <code>Key<\/code> property is always used as a key during matching, or the value is forwarded when it is not set<\/p>\n<p><code>ConverterParameter<\/code> &#8212;\u00a0\u00a0the value from the binding&#8217;s property <code>ConverterParameter<\/code> is always used as the key during matching, or the value is passed through when it is not set<\/p>\n<p><code>PreferManual<\/code> &#8212; if <code>manual Key<\/code> is explicitly set, it takes precedence over <code>ConverterParameter<\/code><\/p>\n<p><code>PreferConverterParameter<\/code> &#8212; if <code>ConverterParameter<\/code> is explicitly set, then it takes precedence over manual <code>Key<\/code><\/p>\n<p>Note that <code>SwitchConverter<\/code>, in addition to the usual <code>Case<\/code>, also has <code>TypedCase<\/code>, the main difference of which is matching by value type<\/p>\n<pre><code class=\"xml\">&lt;SwitchConverter ByDefault=\"Undefined value\"> &lt;TypedCase Key=\"system:String\" Value=\"String value\" \/> &lt;Case Key=\"0\" Value=\"Zero\" \/> &lt;Case Key=\"1\" Value=\"One\" \/> &lt;TypedCase Key=\"system:Int32\" Value=\"Int32 value\" \/> &lt;\/SwitchConverter><\/code><\/pre>\n<p>Sometimes it becomes necessary to debug the value converter. For this purpose, <code>SwitchConverter<\/code> has a <code>DiagnosticKey<\/code> property, if it is been set, then when the data binding is been triggered, diagnostic messages of the following format will be displayed in <code>Trace<\/code><\/p>\n<pre><code class=\"cs\">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);<\/code><\/pre>\n<pre><code class=\"xml\">&lt;SwitchConverter DiagnosticKey=\"UniqDiagnosticKey\" x:Key=\"CodeToBackgroundConverter\" ByDefault=\"White\"> ... &lt;\/SwitchConverter><\/code><\/pre>\n<p><strong>Dependency Value Converter<\/strong><\/p>\n<p>It is also useful to declare <code>Key<\/code>, <code>Value<\/code> and <code>ByDefault<\/code> properties as <code>Dependency Properties<\/code>, that means inheritance of converters and <code>Case<\/code>s from the <code>DependencyObject<\/code> class. Although value converters are usually not elements of the visual tree, which partly limits the work of the data binding mechanism, nevertheless, it remains possible to bind to static resources or descendants of the <code>Binding<\/code> class, for example<\/p>\n<pre><code class=\"xml\">&lt;KeyToValueConverter Key=\"AnyKey\" Value=\"{Binding MatchedValue, Source={StaticResource AnyResource}}\" ByDefault=\"{Binding DefaultValue, Source={StaticResource AnyResource}}\" \/>  &lt;KeyToValueConverter Key=\"AnyKey\" Value=\"{Localizing MatchedTitle}\" ByDefault=\"{Localizing DefaultTitle}\" \/><\/code><\/pre>\n<p><strong>Inline Converter<\/strong><\/p>\n<p><code>Inline Converter<\/code> allow to transfer the values conversion logic \u200b\u200bfrom a separate class that implements the <code>IValueConverter<\/code> interface into the <code>code-behind<\/code> class of a concrete view based on the event model.<\/p>\n<p>This allows to access the view and its individual visual elements from the conversion logic during implementation of complex scenarios that are difficult to implement with the classical approach.<\/p>\n<p>To do this, you need to add the converter declaration to the markup, and into the <code>code-behind<\/code> class define handlers for the corresponding <code>Converting<\/code> and <code>ConvertingBack<\/code> events<\/p>\n<pre><code class=\"xml\">&lt;Grid> &lt;Grid.Resources> &lt;InlineConverter x:Key=\"ComplexInlineConverter\" Converting=\"InlineConverter_OnConverting\" ConvertingBack=\"InlineConverter_OnConverting\" \/> &lt;\/Grid.Resources>  &lt;TextBlock Text=\"{Binding Number, Converter={StaticResource InlineConverter}}\" \/> &lt;\/Grid><\/code><\/pre>\n<pre><code class=\"cs\">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) { \/\/ ... }<\/code><\/pre>\n<p><strong>Aggregate Converter<\/strong><\/p>\n<p>Aggregate converter intends for combining converters into chains, while the value is converted sequentially in the order in which nested converters are declared.<\/p>\n<pre><code class=\"xml\">&lt;AggregateConverter> &lt;StepAConverter \/> &lt;StepBConverter \/> &lt;StepCConverter \/> &lt;\/AggregateConverter><\/code><\/pre>\n<p><strong>App.xaml<\/strong><\/p>\n<p>It is useful to locate generic value converters in a separate Resource Dictionary and then merge them as global resources into the App.xaml file. This allows to reuse value converters in different views without re-declaring them.<\/p>\n<pre><code class=\"xml\">&lt;Application xmlns=\"http:\/\/xamarin.com\/schemas\/2014\/forms\" xmlns:x=\"http:\/\/schemas.microsoft.com\/winfx\/2009\/xaml\" x:Class=\"Any.App\"> &lt;Application.Resources> &lt;ResourceDictionary> &lt;ResourceDictionary.MergedDictionaries> &lt;ResourceDictionary Source=\"AppConverters.xaml\" \/> ... &lt;\/ResourceDictionary.MergedDictionaries> &lt;\/ResourceDictionary> &lt;\/Application.Resources> &lt;\/Application><\/code><\/pre>\n<p><strong>Ace Framework<\/strong><\/p>\n<p>Examples of implementation of the presented converters can be found into the <code>Ace Framework<\/code> library <a href=\"https:\/\/gitlab.com\/Makeloft-Studio\/Ace\/-\/tree\/master\/Ace.Zest\/Converters\" rel=\"noopener noreferrer nofollow\">gitlab<\/a> <a href=\"https:\/\/bitbucket.org\/Makeloft\/ace\/src\/master\/Ace.Zest\/Converters\/\" rel=\"noopener noreferrer nofollow\">bitbucket<\/a><\/p>\n<p>With gratitude for your attention and interest!<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/526480\/\"> https:\/\/habr.com\/ru\/articles\/526480\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-413442","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/413442","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=413442"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/413442\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=413442"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=413442"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=413442"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}