WPF / 30.03.2010

Konvertor - nejlepší přítel člověka 1

T
Tomáš Pastorek
Autor článku
5 min
Čas čtení

Součástí WPF je propracovaný DataBinding (více ve článku DataBinding a DataTemplate), kterým je možné přiřazovat hodnoty z různých zdrojů dat (vlastnosti objektů, kolekce dat, apod.) v uživatelském rozhraní. Určitě vás napadne, že ne všechny zdroje a cíle jsou stejného typu. A máte samozřejmě pravdu. Také vás může napadnout, že je občas potřeba data nějakým způsobem upravit, než se dostanou ke svému cíli. Naštěstí existuje řešení: Ať na úpravu typu dat nebo na určitou datovou transformaci můžeme použít konvertor (Converter).

Co to tedy je? Konvertor (Converter) je třída zděděná z interface IValueConverter pro jednoduchý konvertor nebo z interface IMultiValueConverter pro transformace vyžadující více zdrojů dat. V dnešním dílu se budeme zabývat pouze jednoduchým konvertorem implementujícím interface IValueConverter. Tento interface obsahuje pouze dvě metody: Convert(...) pro převod ze zdroje do cíle a ConvertBack(...) pro převod z cíle do zdroje. Pro názornost je činnost konvertoru vysvětlena následujícím obrázkem:

converter1

Ve zkratce:

  • Jako cíl DataBindingu můžeme použít pouze Dependency Property (a tu může obsahovat pouze Dependency object). Stručně tento základní mechanismus popisuje článek Dependency Properties (EN).
  • Zdroj dat pro DataBinding může být libovolná vlastnost (Property) jakéhokoli objektu.
  • Mezi zdroj a cíl DataBindingu se vloží konvertor, který může data upravit.
  • Pro směr dat ze zdroje do cíle se používá metoda Convert(...)
  • Pro opačný směr se používá ConvertBack(...)

Příklad

Pro názornou ukázku jsem zvolil velmi jednoduchý příklad. Budeme chtít, aby se nějaký TextBox zneplatnil (IsEnabled = false), pokud je určitý CheckBox zaškrtnutý (IsChecked = true). Je zde vidět, proč pouze DataBinding nepomůže – je potřeba převést logiku zaškrtávání na opačnou hodnotu bool. Tedy něco jako: “value = !value”. Logika konvertoru je tedy velmi jednoduchá:

[System.Windows.Data.ValueConversion(typeof(bool), typeof(bool))]
public class InverseBoolConverter :  System.Windows.Data.IValueConverter
{

    public object Convert(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        if (targetType != typeof(bool))
            throw new InvalidOperationException("Target is not a boolean.");

        return !(bool)value;
    }

    public object ConvertBack(object value, Type targetType, object parameter,
        System.Globalization.CultureInfo culture)
    {
        // pouze převod ze zdroje do cíle
        throw new NotSupportedException();
    }
}

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Ke kódu jenom pár poznámek:

  • ValueConversionAttribute nemá na implementaci žádný vliv a slouží pouze pro vývojové nástroje, které mohou konvertor najít podle daných zdrojových a cílových typů. Konvertor bude fungovat i bez tohoto atributu.
  • Protože při psaní XAMLu neprobíhá silně typová kontrola, je dobré ošetřit typy dat na vstupu konvertoru.

Po vytvoření konvertoru jej musíme nadefinovat v sekci Resources, abychom ho mohli dále použít. Pokud bychom chtěli konvertor používat v rámci celého elementu(objektu) Window, bude definice vypadat takto:

<Window.Resources>
     <local:InverseBoolConverter x:Key="InverseConverter" />
</Window.Resources>

.csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

Pokud bychom chtěli nyní použít vytvořenou instanci naší třídy InverseBoolConverter stačí se na ni odkázat pomocí jména a markup extension StaticResource - {StaticResource InverseConverter}.

Celý kód v XAMLu:

<Window x:Class="ConverterTest.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ConverterTest"
    Title="Converter Test - Xaml.cz" Height="300" Width="300">
    <Window.Resources>
        <local:InverseBoolConverter x:Key="InverseConverter" />
    </Window.Resources>
    <StackPanel Margin="10">
        <CheckBox x:Name="check1" Content="Zaškrtni mě :)" Padding="10,0,0,10" />
        <TextBox MinLines="3" IsEnabled="{Binding ElementName=check1,Path=IsChecked,Converter={StaticResource InverseConverter}}">Textbox...</TextBox>
    </StackPanel>
</Window>

Zde je názorně vidět použití konvertoru: Vlastnost IsEnabled TextBoxu je provázána DataBindingem s vlastností IsChecked [CheckBox](http://msdn.microsoft.com/en-us/library/system.windows.controls.checkbox.aspx)u, který je pojmenovaný “check1”. Mezi tuto vazbu se použil konvertor z přikladu pro otočení hodnoty bool, který je v sekci Resources nadefinován pod názvem “InverseConverter”.

Závěr

Možná z tohoto článku na první pohled nebyla zřejmá krása použití konvertoru pro tak jednoduchý příklad. Ale stačí, když tento InverseBoolConverter už jednou budeme mít v projektu a uvidíte, že se jeho použití najde vícekrát. A o elegantní znovupoužitelné řešení jde přece vždy. :)

Komentáře (1)

Buďte první, kdo napíše komentář.
X
xaml.cz

Komunitní blog zaměřený na XAML, WPF, Silverlight a budoucnost desktopových a mobilních technologií.

© 2026 xaml.cz

Svelte 5 Tailwind CSS Bun