« Converter » : différence entre les versions

De Banane Atomic
Aller à la navigationAller à la recherche
 
Ligne 234 : Ligne 234 :
= Examples =
= Examples =
== InverseBooleanConverter ==
== InverseBooleanConverter ==
<kode lang='cs' collapsed>
<filebox fn='InverseBooleanConverter.cs' collapsed>
</kode>
[ValueConversion(typeof(bool), typeof(bool))]
public class InverseBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool booleanValue)
        {
            return !booleanValue;
        }
 
        return DependencyProperty.UnsetValue;
    }
 
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Convert(value, targetType, parameter, culture);
    }
}
</filebox>


<filebox fn='MyWindow.xaml' collapsed>
<filebox fn='MyWindow.xaml' collapsed>
<Window xmlns:converters="clr-namespace:MyApp.Converters">
<Window.Resources>
 
     <converters:InverseBooleanConverterx:Key="InverseBooleanConverter" />
     <Window.Resources>
</Window.Resources>
        <converters:BooleanToCursorConverter x:Key="BooleanToCursorConverter" />
    </Window.Resources>


    <!-- has to be defined after the converter -->
<RadioButton Content="R1" IsChecked="{Binding IsR1Selected}"></RadioButton>
    <Window.Cursor>
<RadioButton Content="R2" IsChecked="{Binding IsR1Selected, Converter={StaticResource InverseBooleanConverter}}"></RadioButton>
        <Binding Path="IsBusy"
                Converter="{StaticResource BooleanToCursorConverter}" />
    </Window.Cursor>
</filebox>
</filebox>



Dernière version du 7 juillet 2022 à 17:55

Built-in converter

BooleanToVisibilityConverter

BooleanToVisibilityConverter is located in System.Windows.Controls.

Xaml.svg
<Window>
    <Window.Resources>
        <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
    </Window.Resources>

    <TextBlock Visibility="{Binding IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}" />

InvertedBooleanToVisibilityConverter

InvertedBooleanToVisibilityConverter.cs
public class InvertedBooleanToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var flag = false;
        if (!(value is bool flag) && value is bool? nullable)
        {
            flag = nullable.Value;
        }

        return (object) (Visibility) (flag ? 2 : 0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        => (object) (bool) (!(value is Visibility visibility) ? 0 : (visibility == Visibility.Collapsed ? 1 : 0));
}

Null to boolean

This more a binding option than a converter.
Set a specific value when the binding value is Null.

Xaml.svg
<CheckBox IsChecked="{Binding MyProperty, TargetNullValue=False}" />

ValueConverter

Xaml.svg
<UserControl xmlns:conversion="clr-namespace:MyNamespace.Conversion">

    <UserControl.Resources>
        <conversion:ListToVisibilityConverter x:Key="ListToVisibilityConverter" />
    </UserControl.Resources>

    <TextBlock Visibility="{Binding MyList, Converter={StaticResource ListToVisibilityConverter}}" />
ListToVisibilityConverter.cs
namespace MyNamespace.Conversion
{
    // L'attribut ValueConversion est optionel,
    // il permet de spécifier le type d'entrée et le type de sortie
    [ValueConversion(typeof(IEnumerable), typeof(Visibility))]
    public class ListToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is IEnumerable itemCollection)
            {
                return itemCollection.Cast<object>().Any() ? Visibility.Visible : Visibility.Collapsed;
            }

            return DependencyProperty.UnsetValue;
        }

        // Conversion inverse non-implémentée
        public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
            throw new NotSupportedException();
            return null;
        }
    }
}

Inverted convertion

Inverted convertion with IsInverted property

Xaml.svg
<UserControl xmlns:conversion="clr-namespace:MyNamespace.Conversion">

    <UserControl.Resources>
        <conversion:ListToVisibilityConverter x:Key="EmptyListToCollapsedConverter" />
        <conversion:ListToVisibilityConverter x:Key="EmptyListToVisibleConverter"
                                              IsInverted="true" />
    </UserControl.Resources>

    <TextBlock Visibility="{Binding MyList, Converter={StaticResource EmptyListToCollapsedConverter}}" />
    <TextBlock Visibility="{Binding MyList, Converter={StaticResource EmptyListToVisibleConverter}}" />
ListToVisibilityConverter.cs
namespace MyNamespace.Conversion
{
    [ValueConversion(typeof(IEnumerable), typeof(Visibility))]
    public class ListToVisibilityConverter : IValueConverter
    {
        public bool IsInverted { get; set; }

        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            var visibleFlag = false;
            if (value is IEnumerable itemCollection)
            {
                visibleFlag = itemCollection.Cast<object>().Any();
            }
            else
            {
                return DependencyProperty.UnsetValue;
            }

            if (this.IsInverted)
            {
                visibleFlag = !visibleFlag;
            }

            return visibleFlag ? Visibility.Visible : Visibility.Collapsed;
        }

        // Conversion inverse non-implémentée
        public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Inverted convertion with ConverterParameter

The ConverterParameter property can not be bound because it is not a dependency property.
Use MultiValueConverter as an alternative.
Xaml.svg
<TextBlock Visibility="{Binding MyList, Converter={StaticResource ListToVisibilityConverter}, ConverterParameter=Inverted}" />
ListToVisibilityConverter.cs
[ValueConversion(typeof(IEnumerable), typeof(Visibility))]
public class ListToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var visibleFlag = false;
        if (value is IEnumerable itemCollection)
        {
            visibleFlag = itemCollection.Cast<object>().Any();
        }
        else
        {
            return DependencyProperty.UnsetValue;
        }

        if (parameter != null && Enum.TryParse(parameter.ToString(), true, out Parameters invert) && invert == Parameters.Inverted)
        {
            visibleFlag = !visibleFlag;
        }

        return visibleFlag ? Visibility.Visible : Visibility.Collapsed;
    }

    // Conversion inverse non-implémentée
    public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }

    private enum Parameters
    {
        Normal,
        Inverted
    }

MultiValueConverter

Xaml.svg
<UserControl xmlns:conversion="clr-namespace:MyNamespace.Conversion">

    <UserControl.Resources>
        <conversion:TakeItemsConverter x:Key="TakeItemsConverter"/>
    </UserControl.Resources>

    <ItemsControl>
        <ItemsControl.ItemsSource>
            <MultiBinding Converter="{StaticResource TakeItemsConverter}">
                <Binding Path="Items" />
                <Binding Path="MaxNumberOfItemsToDisplay" />
            </MultiBinding>
        </ItemsControl.ItemsSource>
    </ItemsControl>
Csharp.svg
namespace MyNamespace.Conversion
{
    // L'attribut ValueConversion n'est pas utilisé ici car il n'est pas adapté
    // au MultiValueConverter : il ne peut définir qu'un seul type d'entrée
    public class TakeItemsConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            // expect 2 values, an IEnumerable and an int
            if (values != null
                && values.Length == 2
                && values[0] is IEnumerable itemCollection
                && values[1] != null
                && int.TryParse(values[1].ToString(), NumberStyles.Integer, culture, out var numberOfItemsToTake))
            {
                return itemCollection.Cast<object>().Take(numberOfItemsToTake);
            }

            return DependencyProperty.UnsetValue;
        }

        // Conversion inverse non-implémentée
        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

CalcBinding

Install Nuget package CalcBinding.

MainView.xaml
<Window xmlns:c="clr-namespace:CalcBinding;assembly=CalcBinding">
    <RadioButton Content="R1" IsChecked="{Binding IsR1Selected}"></RadioButton>
    <RadioButton Content="R2" IsChecked="{c:Binding !IsR1Selected}"></RadioButton>
</Window>

Examples

InverseBooleanConverter

InverseBooleanConverter.cs
[ValueConversion(typeof(bool), typeof(bool))]
public class InverseBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool booleanValue)
        {
            return !booleanValue;
        }

        return DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Convert(value, targetType, parameter, culture);
    }
}
MyWindow.xaml
<Window.Resources>
    <converters:InverseBooleanConverterx:Key="InverseBooleanConverter" />
</Window.Resources>

<RadioButton Content="R1" IsChecked="{Binding IsR1Selected}"></RadioButton>
<RadioButton Content="R2" IsChecked="{Binding IsR1Selected, Converter={StaticResource InverseBooleanConverter}}"></RadioButton>

BooleanToCursorConverter

Cs.svg
[ValueConversion(typeof(bool), typeof(Cursor))]
public sealed class BooleanToCursorConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool isBusy)
        {
            return isBusy ? Cursors.Wait : Cursors.Arrow;
        }

        return DependencyProperty.UnsetValue;
    }

    public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
MyWindow.xaml
<Window xmlns:converters="clr-namespace:MyApp.Converters">

    <Window.Resources>
        <converters:BooleanToCursorConverter x:Key="BooleanToCursorConverter" />
    </Window.Resources>

    <!-- has to be defined after the converter -->
    <Window.Cursor>
        <Binding Path="IsBusy"
                 Converter="{StaticResource BooleanToCursorConverter}" />
    </Window.Cursor>