Erjon
Erjon

Reputation: 930

Using FindResource in an IValueConverter

I have this value converter which converts a number to a brush color. What I need to do is to change the line return Brushes.Red; into return (Brush)FindResource("PrimaryHueMidBrush");, so I can return the color of the main theme. The problem is that I don't know how to declare (Brush)FindResource("PrimaryHueMidBrush");. Any help is welcome. Thank you in advance.

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    double.TryParse(value.ToString(), out double val);

    if (val == 1)
    {
        return Brushes.Red;
    }
    else if(val == 0.5)
    {
        return Brushes.MediumVioletRed;
    }
    else if(val==0)
    {
        return Brushes.Transparent;
    }
    else
    {
        return Brushes.Transparent;
    }
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
    throw new NotImplementedException();
}

Upvotes: 3

Views: 1373

Answers (2)

Clemens
Clemens

Reputation: 128077

Instead of calling FindResource in the converter, you'd better add one or more properties for the dynamic Brushes:

public class YourConverter : IValueConverter
{
    public Brush FirstBrush { get; set; }
    public Brush SecondBrush { get; set; }

    public object Convert(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        double val = (double)value;

        if (val >= 1)
        {
            return FirstBrush;
        }

        if (val >= 0.5)
        {
            return SecondBrush;
        }

        return Brushes.Transparent;
    }

    public object ConvertBack(
        object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

You would declare it in the Resources of your Application or Window like this:

<local:YourConverter x:Key="YourConverter"
    FirstBrush="{StaticResource PrimaryHueMidBrush}"
    SecondBrush="MediumVioletRed"/>

Upvotes: 8

Manfred Radlwimmer
Manfred Radlwimmer

Reputation: 13394

To access FindResource you need a FrameworkElement so the best way to do this would probably be to use a MultiValueConverter instead and pass the element that uses the converter as a second value.

Converter:

public class WhateverThisIsCalledConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        // Insert type- and sanity-checks here
        double val = (double)values[0];
        FrameworkElement callingElement = (FrameworkElement)values[1];

        if (val >= 1)
        {
            return callingElement.FindResource("PrimaryHueMidBrush");
        }
        if (val >= 0.5)
        {
            return Brushes.MediumVioletRed;
        }

        return Brushes.Transparent;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        return Enumerable.Repeat(DependencyProperty.UnsetValue, targetTypes.Length).ToArray();
    }
}

Usage in XAML:

<Window.Resources>
    <local:WhateverThisIsCalledConverter x:Key="Converter"/>
    <SolidColorBrush Color="Red" x:Key="PrimaryHueMidBrush"/>
</Window.Resources>
<Grid>
    <Grid.Background>
        <MultiBinding Converter="{StaticResource Converter}">
            <Binding Path="Value"/>
            <Binding RelativeSource="{RelativeSource Self}"/>
        </MultiBinding>
    </Grid.Background>
</Grid>

Couple of notes on your current implementation:

  • Try avoiding == on doubles, they are not infinitely precice.
  • You don't need all those elses when you return in the if before.
  • The ConvertBack method should be implemented (Free choice of other Exceptions, Binding.DoNothing and DependencyProperty.UnsetValue).
  • If you know your value is a double, simply cast it instead.

Upvotes: 0

Related Questions