Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Databinding on a IValueConverter

Does anybody know if it is possible to do databinding on an IValueConverter based class?

I have the following converter:

[ValueConversion(typeof(int), typeof(Article))]
public class LookupArticleConverter : FrameworkElement, IValueConverter {
    public static readonly DependencyProperty ArticlesProperty = DependencyProperty.Register("Articles", typeof(IEnumerable<Article>), typeof(LookupArticleConverter)); 

    public IEnumerable<Article> Articles
    {
        get { return (IEnumerable<Article>)GetValue(ArticlesProperty); }
        set { SetValue(ArticlesProperty, value); }
    }

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
        ...
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
        ...
    }
}

It's purpose is to lookup an article in a list by its Id, and return that article.

However, I'd like to fill the Articles property by databinding a collection to it, like this:

<local:LookupArticleConverter Articles="{Binding Articles}" x:Key="LookupArticle"/>

But this doesn't seem to work. The setter method is never called. The source property contains an actual nonempty collection, so that's not the problem.

There's no error messages regarding binding in the output log, neither.

Any clues?

like image 286
Inferis Avatar asked Mar 09 '09 09:03

Inferis


People also ask

What is IValueConverter?

The IValueConverter interface consists of two methods, Convert() and ConvertBack() . Convert method gets called when source updates target object. ConvertBack method gets called when target updates source object.

What are methods present in IValueConverter interface?

As advertised, it just implements the two required methods, called Convert() and ConvertBack(). The Convert() methods assumes that it receives a string as the input (the value parameter) and then converts it to a Boolean true or false value, with a fallback value of false.

How do I bind a converter?

Create a converter by implementing the IValueConverter interface and implementing the Convert method. That method should return an object that is of the same type as the dependency property that the binding targets, or at least a type that can be implicitly coerced or converted to the target type.

What is binding why binding of data is necessary?

Data binding is the process that establishes a connection between the app UI and the data it displays. If the binding has the correct settings and the data provides the proper notifications, when the data changes its value, the elements that are bound to the data reflect changes automatically.


2 Answers

So, the problem is that resources are not part of the visual tree. To make this work you have to:

1. Make your ValueConverter inherit Freezable

 public class CustomConverter : Freezable, IValueConverter
 {

    public static readonly DependencyProperty LookupItemsProperty =
        DependencyProperty.Register("LookupItems", typeof(IEnumerable<LookupItem>), typeof(CustomConverter), new PropertyMetadata(default(IEnumerable<LookupItem>)));

    public IEnumerable<LookupItem> LookupItems
    {
        get { return (IEnumerable<LookupItem>)GetValue(LookupItemsProperty); }
        set { SetValue(LookupItemsProperty, value); }
    }

    #region Overrides of Freezable

    /// <summary>
    /// When implemented in a derived class, creates a new instance of the <see cref="T:System.Windows.Freezable"/> derived class.
    /// </summary>
    /// <returns>
    /// The new instance.
    /// </returns>
    protected override Freezable CreateInstanceCore()
    {
        return new CustomConverter();
    }

    #endregion Overrides of Freezable

    // ... Usual IValueConverter stuff ...

}

2. Bind to the visual tree using Binding ElementName

<UserControl (...) x:Name=myUserControl> 
<UserControl.Resources>
<CustomConverter x:Key="customConverter"
                    LookupItems="{Binding ElementName=myUserControl, Path=DataContext.LookupItems}"/>
</UserControl.Resources>
like image 173
surfen Avatar answered Sep 24 '22 04:09

surfen


WPF doesn't really support this intrinsically. However, there are some techniques that will allow you to do this, including Josh Smith's virtual branch approach.

like image 44
Kent Boogaart Avatar answered Sep 22 '22 04:09

Kent Boogaart