How to pass a static value to IValueConverter in XAML

16,238

Solution 1

I finally found the answer. The answer was a mix between that of @Shawn Kendrot and another question I asked here: IValueConverter not getting invoked in some scenarios

To summarize the solution for using the IValueConverter I have to bind my control in the following manor:

<phone:PhoneApplicationPage.Resources>
    <Helpers:StaticTextConverter x:Name="TextConverter" />
</phone:PhoneApplicationPage.Resources>

<TextBlock Text="{Binding Converter={StaticResource TextConverter}, ConverterParameter=M62}" />

Since the ID of the text is passed in with the converter parameter, the converter looks almost the same:

public class StaticTextConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (parameter != null && parameter is string)
        {
            return App.StaticTexts.Items.SingleOrDefault(t => t.Name.Equals(parameter)).Content;
        }

        return null;
    }
}

However, as it turns out, the binding and thus the converter is not invoked if it does not have a DataContext. To solve this, the DataContext property of the control just has to be set to something arbitrary:

<TextBlock DataContext="arbitrary" 
           Text="{Binding Converter={StaticResource TextConverter}, ConverterParameter=M62}" />

And then everything works as intended!

Solution 2

The problem lies in your binding. It will check the DataContext, and on this object, it will try to evaluate the properties M62 and ValueboxConsent on that object.

You might want to add static keys somewhere in your application where you can bind to:

<TextBlock Text="{Binding Source="{x:Static M62.ValueboxConsent}", Converter={StaticResource StaticTextConverter}}" />

Where M62 is a static class where your keys are located.. like so:

public static class M62
{
    public static string ValueboxConsent
    {
        get { return "myValueBoxConsentKey"; }
    }
}

Solution 3

If you want to use a value converter, you'll need to pass the string to the parameter of value converter

Xaml:

<TextBlock Text="{Binding Converter={StaticResource StaticTextConverter}, ConverterParameter=M43}"/>

Converter:

public class StaticTextConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (parameter != null)
        {
            return App.StaticTexts.Items.SingleOrDefault(t => t.Name.Equals(parameter)).Content;
        }

        return null;
    }
}

Solution 4

xmlns:prop="clr-namespace:MyProj.Properties;assembly=namespace:MyProj"

<TextBlock Text="{Binding Source={x:Static prop:Resources.MyString}, Converter={StaticResource StringToUpperCaseConverter}}" />
Share:
16,238
Zappel
Author by

Zappel

I have a masters degree in computer science and am now a Senior iOS Developer with a small internet startup.

Updated on June 03, 2022

Comments

  • Zappel
    Zappel almost 2 years

    I would like to use static texts fetched from a web service in my WP7 app. Each text has a Name (the indetifier) and a Content property.

    For example a text could look like this:

    Name = "M43";
    Content = "This is the text to be shown";
    

    I would then like to pass the Name (i.e. the identifier) of the text to an IValueConverter, which would then look up the the Name and return the text.

    I figured the converter to look something like this:

    public class StaticTextConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value != null)
            {
                return App.StaticTexts.Items.SingleOrDefault(t => t.Name.Equals(value)).Content;
            }
    
            return null;
        }
    }
    

    Then in the XAML:

    <phone:PhoneApplicationPage.Resources>
        <Helpers:StaticTextConverter x:Name="StaticTextConverter" />
    </phone:PhoneApplicationPage.Resources>
    
    ...
    
    <TextBlock Text="{Binding 'M43', Converter={StaticResource StaticTextConverter}}"/>
    

    However, this does not seem to work and I am not sure that I pass in the value to the converter correctly.

    Does anyone have some suggestions?

    • Rico Suter
      Rico Suter almost 12 years
      try {Binding M62.ValueboxConsent, Converter={StaticResource StaticTextConverter}}
    • Zappel
      Zappel almost 12 years
      Afraid it does not work.
  • Zappel
    Zappel almost 12 years
    The thing is that the static texts are very simple: A string identifies a text and all texts are simply held in a long list. That's the reason I use LINQ to retrieve it. However, I have updated my question to be more explicit, please have another look. Thank you!
  • Arcturus
    Arcturus almost 12 years
    Yes, but you need to bind to the correct value. And if its not defined on your DataContext object, then your value will always be unknown
  • Zappel
    Zappel almost 12 years
    So there is no way to just pass in some static string?
  • Arcturus
    Arcturus almost 12 years
    You can add a Property on your Converter, and pass it along like so: <Helpers:StaticTextConverter x:Name="StaticTextConverter" MyProperty="Value" />
  • Zappel
    Zappel almost 12 years
    That is also one of the possibilities I have thought of. However, it does not seem to work. If I set a breakpoint in my converter implementation, it is not catched. I don't know if there is something wrong with my setup of the converter, but all other converters that I am using are working fine.
  • Zappel
    Zappel almost 12 years
    It seems to work only when inside a <DataTemplate>. However, I also need it to work independently of that. Any suggestions?
  • Shawn Kendrot
    Shawn Kendrot almost 12 years
    This should work regardless of in/out of DataTemplate. Can you provide a zip/pastebin sample?
  • Zappel
    Zappel almost 12 years
    Your answer is halfway there. I just posted an answer that solves my question. It's a mix between your question and another one. Thank you.
  • FirstOne
    FirstOne almost 8 years
    While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. (This answer got into the 'Low Quality Posts' queue ;) .. )
  • IgorStack
    IgorStack almost 6 years
    Mode=OneWay or OneTime need to be added to the Binding if MyString is a const.