WPF: Is there any way to force converter to update if its property gets changed?
Asked Answered
R

2

6

Intro: Here is a part of my Translator that I use in my app. I want to update all the strings in it when I change the language with a ComboBox.

Problem: I would like to update labels Content when my Converters Property gets changed. Is it possible? This way (how I made it) doesn't update Content if I change CurrentLanguage.

 <Label
      ID:Name="CompanyName"
      Content="{Binding ElementName=CompanyName, Path=Name, Converter={ID:Static Controller:Translator.Instance}}" />

This ComboBox changes my Current value - works

 <ComboBox
        SelectedItem="{Binding Path=CurrentLanguage, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay, Converter={StaticResource FlagConverter}}">

Translator code behind - works (PropertyChanged gets fired)

    public partial class Translator : IValueConverter, INotifyPropertyChanged
    { 
    ...
        private String m_currentLanguage;
        public String CurrentLanguage
        {
            get { return m_currentLanguage; }
            set
            {
                m_currentLanguage = value;
                OnPropertyChanged("CurrentLanguage");
            }
        }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return Get((String)value); // nonrelevant function - works
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return GetOriginal((String)value); // nonrelevant function - works
        }

        #region Events
        public event PropertyChangedEventHandler PropertyChanged;

        protected virtual void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion
    }
Rog answered 14/7, 2015 at 14:7 Comment(6)
This is just odd. You are not even using the converter as a converter. You are binding an element to itself?Epidaurus
@Sinatr I'll take a look at both of them, thanks :) This way however there are no memory leaks =)Rog
@Blam yes I am, it works really good, I just set a converter to use its Name and then i translate it to a string that it can find in my translations .XML, the Name acts as a key to the dictionary :)Rog
But is is not working and it still looks strange to me. meta.stackexchange.com/questions/66377/what-is-the-xy-problemEpidaurus
@Blam I will try MultiValueConverter and will report back, it sounds promising =)Rog
@DourHighArch Thanks, didn't know that, I'm a noob here :PRog
J
3

I see 2 possible solutions:

  • Use a multivalueconverter and bind to Name AND CurrentLanguage
  • More like a hack: Add an eventtrigger to comboxbox.itemchanged and reset the value of Company.Name with Company.Name (setter gets called -> converter gets called)
Jeuz answered 14/7, 2015 at 14:35 Comment(3)
I'll try 1st solution first cause others mentioned it too. I thought of the 2nd one but I wanted a more efficient way to do it cause I don't want want to use members to store things that XAML can manage on its own. Also, I have multiple ItemsControls all over the code which would increase memory usage a lot (Labels + ToolTip translations for each control)Rog
After reading about them for a bit, I found this: blog.csainty.com/2009/12/wpf-multibinding-and.html Looks promising. That's what you get for not learning WPF out of a book, but go by try-fail-learn method :DRog
MultiValueConverter worked as expected, thnaks a lot! (my upvotes do not work due to yet to be high rep)Rog
R
1

Solution: Use MultiBinding + IMultiValueConverter

ComboBox remained the same.

Edited Laber to use MultiBinding.

                <Label
                    ID:Name="CompanyName"
                    <Label.Content>
                        <MultiBinding Converter="{ID:Static Controller:Translator.Instance}">
                            <Binding ElementName="CompanyName" Path="Name"/>
                            <Binding Source="{ID:Static Controller:Translator.Instance}" Path="CurrentLanguage"/>
                        </MultiBinding>
                    </Label.Content>
                </Label>

Changed Translator to IMultiValueConverter:

        public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            if ((values[0] as String).Length <= 0)
                return ""; // prevents error messages for binds on element names

            return Get((String)values[0]);
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }

Thx a lot guys!

Rog answered 15/7, 2015 at 10:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.