Search code examples
c#wpfbindingivalueconverter

Decouple IValueConverter (Disable/Enable a WPF Converter)


It's a way to enable and disable a WPF Converter? Either programmatically or directly from WPF binding a checkbox control to it.

I have this Textbox and Checkbox in my application:

enter image description here

When Checkbox is unchecked I can enter any numeric value, but when I Check the checkbox I want to enable this converter:

<TextBox
Grid.Row="1"
Grid.Column="1"
Margin="0,0,10,0"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
MaxLength="41"
Text="{
    Binding Payload, 
    Mode=TwoWay, 
    Converter={StaticResource HexStringConverter}, 
    UpdateSourceTrigger=PropertyChanged}" 
/>

Also, this is the converter class:

public class HexStringConverter : IValueConverter
    {
        private string lastValidValue;
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string ret = null;

            if (value != null && value is string)
            {
                var valueAsString = (string)value;
                var parts = valueAsString.ToCharArray();
                var formatted = parts.Select((p, i) => (++i) % 2 == 0 ? String.Concat(p.ToString(), " ") : p.ToString());
                ret = String.Join(String.Empty, formatted).Trim();
            }

            return ret;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            object ret = null;
            if (value != null && value is string)
            {
                var valueAsString = ((string)value).Replace(" ", String.Empty).ToUpper();
                ret = lastValidValue = IsHex(valueAsString) ? valueAsString : lastValidValue;
            }

            return ret;
        }


        private bool IsHex(string text)
        {
            var reg = new System.Text.RegularExpressions.Regex(@"^[0-9A-Fa-f\[\]]*$");
            return reg.IsMatch(text);
        }
    }

Solution

  • As usual in WPF, there are many ways to do this.

    One way is to use a trigger to change the binding given to Text, something like:

    <TextBlock ....>
        <TextBlock.Style>
            <Style TargetType="TextBlock">
                <Setter Property="Text" Value="{Binding Payload}"/>
                <Style.Triggers>
                    <DataTrigger Binding="{Binding IsChecked, ElementName=NameOfCheckBox}" Value="True">
                        <Setter Property="Text"
                                Value="{Binding Payload, Converter={StaticResource HexToStringConverter}}"/>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </TextBlock.Style>
    </TextBlock>
    

    Another way is to use an IMultiValueConverter:

    public class HexStringConverter : IMultiValueConverter
    {
        public object Convert (object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values.Length != 2 ||
                values[0] is not string str ||
                values[1] is not bool isEnabled)
            {
                return DependencyProperty.UnsetValue;
            }
     
            if (isEnabled)
            {
                // Do the actual conversion
            }
            else
            {
                return str;
            }
        }
    }
    

    Then:

    <TextBlock ...>
        <TextBlock.Text>
            <MultiBinding Converter="{StaticResource HexToStringConverter}">
                <Binding Path="Payload"/>
                <Binding Path="IsChecked" ElementName="NameOfCheckBox"/>
            </MultiBinding>
        </TextBlock.Text>
    </TextBlock>