Click here to Skip to main content
15,893,381 members
Articles / Desktop Programming / WPF

Bindable Converter, Converter Parameter and StringFormat

Rate me:
Please Sign up or sign in to vote.
4.87/5 (12 votes)
18 Sep 2012CPOL5 min read 77.4K   1.5K   20  
How to work around that Binding's Converter, ConvertParameter and StringFormat cannot be specified as dynamic Bindings.
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Data;
using System.Windows.Markup;

namespace BindableConverterParameter
{
    public class BindableBinding : MarkupExtension
    {
        private readonly Binding binding = new Binding ( );

        public BindableBinding ( )
        {

        }

        public BindableBinding (PropertyPath path )
        {
            binding.Path = path;
        }

        public PropertyPath Path
        {
            get
            {
                return binding.Path;
            }
            set
            {
                binding.Path = value;
            }
        }

        public Object Source
        {
            get
            {
                return binding.Source;
            }
            set
            {
                binding.Source = value;
            }
        }

        public RelativeSource RelativeSource
        {
            get
            {
                return binding.RelativeSource;
            }
            set
            {
                binding.RelativeSource = value;
            }
        }

        public String ElementName
        {
            get
            {
                return binding.ElementName;
            }
            set
            {
                binding.ElementName = value;
            }
        }

        public String XPath
        {
            get
            {
                return binding.XPath;
            }
            set
            {
                binding.XPath = value;
            }
        }

        public BindingMode Mode
        {
            get
            {
                return binding.Mode;
            }
            set
            {
                binding.Mode = value;
            }
        }

        public CultureInfo ConverterCulture
        {
            get
            {
                return binding.ConverterCulture;
            }
            set
            {
                binding.ConverterCulture = value;
            }
        }

        public object ConverterParameter
        {
            get;
            set;
        }

        private Binding _converterParameterBinding;

        public Binding ConverterParameterBinding
        {
            get
            {
                return _converterParameterBinding;
            }
            set
            {
                _converterParameterBinding = value;
            }
        }

        public IValueConverter Converter
        {
            get;
            set;
        }

        private Binding _converterBinding;

        public Binding ConverterBinding
        {
            get
            {
                return _converterBinding;
            }
            set
            {
                _converterBinding = value;
            }
        }

        public String StringFormat
        {
            get;
            set;
        }

        private Binding _stringFormatBinding;

        public Binding StringFormatBinding
        {
            get
            {
                return _stringFormatBinding;
            }
            set
            {
                _stringFormatBinding = value;
            }
        }


        public override object ProvideValue ( IServiceProvider serviceProvider )
        {

            MultiBinding multiBinding = new MultiBinding ( );
            multiBinding.Mode = binding.Mode;
            multiBinding.ConverterCulture = binding.ConverterCulture;
            multiBinding.Converter = new InternalConverter ( this );
            multiBinding.Bindings.Add ( binding );

            if ( ConverterParameterBinding != null )
            {
                multiBinding.Bindings.Add ( ConverterParameterBinding );
            }
            else
            {
                multiBinding.ConverterParameter = ConverterParameter;
            }

            if ( ConverterBinding != null )
            {
                multiBinding.Bindings.Add ( ConverterBinding );
            }

            if ( StringFormatBinding != null )
            {
                multiBinding.Bindings.Add ( StringFormatBinding );
            }

            return multiBinding.ProvideValue ( serviceProvider );
        }

        private class InternalConverter : IMultiValueConverter
        {
            private readonly BindableBinding binding;
            private IValueConverter lastConverter;
            private object lastConverterParameter;

            public InternalConverter ( BindableBinding binding )
            {
                this.binding = binding;
            }

            object IMultiValueConverter.Convert ( object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture )
            {
                int valueIndex = 1;

                object converterParameter = parameter;
                if ( binding.ConverterParameterBinding != null )
                {
                    converterParameter = values[valueIndex++];
                }
                lastConverterParameter = converterParameter;

                IValueConverter converter = binding.Converter as IValueConverter;
                if ( binding.ConverterBinding != null )
                {
                    converter = values[valueIndex++] as IValueConverter;
                }
                lastConverter = converter;

                String stringFormat = binding.StringFormat as String;
                if ( binding.StringFormatBinding != null )
                {
                    stringFormat = values[valueIndex++] as String;
                }

                object value = values[0];
                if ( converter != null )
                {
                    value = converter.Convert ( value, targetType, converterParameter, culture );
                }
                if ( stringFormat != null )
                {
                    value = String.Format ( stringFormat, value );
                }
                return value;
            }

            object[] IMultiValueConverter.ConvertBack ( object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture )
            {

                if ( lastConverter != null )
                {
                    return new object[] { lastConverter.ConvertBack ( value, targetTypes[0], lastConverterParameter, culture ) };

                }
                else
                {
                    return new object[] { value };
                }
            }
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
Sweden Sweden
Henrik Jonsson is a Microsoft Professional Certified Windows Developer (MCPD) that currently works as an IT consultant in Västerås, Sweden.

Henrik has worked in several small and large software development projects in various roles such as architect, developer, CM and tester.

He regularly reads The Code Project articles to keep updated about .NET development and get new ideas. He has contributed with articles presenting some useful libraries for Undo/Redo, Dynamic Linq Sorting and a Silverlight 5 MultiBinding solution.

Comments and Discussions