Search code examples
c#.netwpfxamlidataerrorinfo

WPF Value Converter to replace error code with localized string


I have a viewmodel implementing the IDataErrorInfo interface for validation, for an error it produces a string which is a key in the resource dictionary for a localized string describing the error. However when trying to apply the following style and template to the textbox I get the red border but no tooltip, however removing my converter and using the default one gives me the tooltip but obviously not the localized string.

Can you see what I am doing wrong and/or if there is a better way of doing this?

class MessageCodeToMessageConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (value != null)
        {
            string messageCode = (string)value;
            try
            {
                return (string)App.Current.Resources[messageCode];
            }
            catch (Exception)
            {
                return messageCode;
            }
        }
        else
        {
            return null;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return "";
    }
}

        <local:MessageCodeToMessageConverter x:Key="Converter"></local:MessageCodeToMessageConverter>
        <Style x:Key="TextBox" TargetType="TextBox">
            <Style.Triggers>
                <Trigger Property="Validation.HasError" Value="true">
                    <Setter Property="ToolTip" Value="{Binding RelativeSource={x:Static RelativeSource.Self}, Path=(Validation.Errors)[0].ErrorContent, Converter={StaticResource Converter}}"/>
                </Trigger>
            </Style.Triggers>
        </Style>
        <ControlTemplate x:Key="ErrorTemplate">
            <DockPanel LastChildFill="True">
                <Border BorderBrush="Red" BorderThickness="1">
                    <AdornedElementPlaceholder />
                </Border>
            </DockPanel>
        </ControlTemplate>

Solution

  • In my opinion if your resource key is defined in the App.xaml then it should work. But your resource key is probably in resource in some user control. (string)App.Current.Resources[messageCode]; search only in the App.xaml resource. Solution for you can be use multivalueconverter

    class MessageCodeToMessageConverter : IMultiValueConverter
    {
    public object Convert(object[] values, Type targetType, object parameter,     System.Globalization.CultureInfo culture)
    {
        FrameworkElement targetObject = values[0] as FrameworkElement;
        if (targetObject == null)
        {
           return DependencyProperty.UnsetValue;
        }
        if (value != null)
        {
            string messageCode = (string)values[1];
            try
            {
                return targetObject.FindResource(messageCode);
            }
            catch (Exception)
            {
                return messageCode;
            }
        }
        else
        {
            return null;
        }
    }
    
    public object ConvertBack(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return "";
    }
    }
    

    and

    <Style x:Key="TextBox" TargetType="{x:Type TextBox}">
      <Style.Triggers>
    <Trigger Property="Validation.HasError" Value="true">
      <Setter Property="ToolTip">
        <Setter.Value>
            <MultiBinding Converter="{StaticResource Converter}">
                <MultiBinding.Bindings>
                    <Binding RelativeSource="{RelativeSource Self}" />
                    <Binding RelativeSource="{x:Static RelativeSource.Self}" Path="(Validation.Errors)[0].ErrorContent" />
                </MultiBinding.Bindings>
            </MultiBinding>
        </Setter.Value>
      </Setter>
    </Trigger>
    </Style.Triggers>
    </Style>