none
How can I bind a ConverterParameter value ?

    Question

  • I would like to make a textblock display the remaining time of an operation. The bound object has two properties:  ElapsedTime and TotalDuration, both of type TimeSpan.

    I thought the following should work, but it doesn't because the parameter passed to my custom converter is a Binding object, instead of the result of the binding:

    <TextBlock 
        Text="{Binding ElapsedTime,
            Mode=OneWay,
            ConverterParameter={Binding TotalDuration},
            Converter={StaticResource RemainingTimeConverter}}" />


    The RemainingTimeConverter is implemented to subtract the "value" from the "parameter" and return a string representation of the resultant TimeSpan value.


    Why isn't the inner Binding evaluated and its value passed to the outter binding ConverterParameter ?   Is this by design ?   If that's the case what's the use of having ConverterParameter if I can only use harcoded values ?



    Monday, May 01, 2006 8:28 PM

Answers

  • The answer is straight-forward, but not what you want to hear.

    You can only target a binding at DependencyProperty on a DependencyObject. Binding does not inherit from DO, so you can't binding the converter parameter.

    If you want other state passed into a converter, you may have to subclass the desired obect and add new properties (as has been suggested).

    Monday, July 24, 2006 5:41 AM

All replies

  • Does anyone know if binding inside bindings are supported ?
    Friday, May 05, 2006 7:13 PM
  • Why not create a class that would contain your information ?

    Then you instantiate your class with XAML, and pass it as a parameter.

    create class MyTimeDuration with property for TotalDuration.

    in XAML you add in resources:
    <(namespace of class):MyTimeDuration x:Key="MyDuration">

    Then you pass the key as the ConvertParameter like:

    ConvertParameter={StaticResource MyDuration}

    You can also add public functions to reset your duration such that you can bind it to a button.

    Hope this helps.
    Saturday, May 06, 2006 3:22 PM
  • Yes, I could instantiate a helper class in XAML just to do that but that would be a workaround and not elegant. I have also found other tricks I could do but I am looking for the appropriate solution since the goal of the project I am working on is just to learn WPF.

    It would be very strange to be limited to XAML hardcoded values (and resources) when setting the ConvertParameter property, don't you agree ?

    Saturday, May 06, 2006 6:57 PM
  • how did you solve this

    can you give me an example

     

    Thanks

    Sunday, May 07, 2006 12:19 PM
    Moderator
  • Could someone help me with this

    Thanks

    Monday, May 08, 2006 4:49 PM
    Moderator
  • If you are writing a type converter and, like me, you are unable to pass a runtime parameter to that converter then you just increasing the coupling between the converter and the value that you want to pass.  For example, suppose you can't pass a parameter to a function (for some reason). Then, instead of passing the parameter you could create a global variable, a public static property or a member variable and access it directly from the function. The function would not be generic anymore, instead very coupled, but it would solve the problem (and probably create others) .  The solution someone suggested above is pretty much like that but in XAML.  I am looking for the correct solution.

    I am not very familiar with MarkupExtensions. However, I believe it may be possible to write one to replace "Binding" where we could solve this problem in a more appropriate manner.




    Monday, May 08, 2006 5:28 PM
  • My situation is I have a customcontrol and  in the that I am using a converter which needs a parameter .this will have the value with which the data value will get multiplied, this will not be known at the design time and will be calculated in codebehind.
    Monday, May 08, 2006 5:44 PM
    Moderator
  • You have to figure out a way to pass the instance of the custom control as a parameter to the converter.  Then, inside, the converter access the property on that instance.

    I don't know how you can pass an instance of the custom control in XAML.  Maybe you can pass a StaticResource which in turn could povide the instance ...

    What is strange for me is that it's easy to assign a Name to the objects we declare in XAML.  However, I have never seem a way to refer to those instances by the Name in XAML.  Isn't this a design oversight ?

     

     

     

    Monday, May 08, 2006 5:55 PM
  • I was trying to somehow get that

    I was able to access a property in the customcontrol like this

    <Binding Path="prop1" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type local:CustomControl1}}"></Binding>

    but the for another property, I need to multiply that with another property in the control

    that is where I am having issues

    Monday, May 08, 2006 6:12 PM
    Moderator
  • If you want to multiply a property by another property in the same instance, why don't you create a third property that multiplies the first two and just bind to that property ?

     

    Monday, May 08, 2006 6:18 PM
  • my mistake, the second one is not property on the control it is bound to a data ( a data element in the bound data)

     

     

    Monday, May 08, 2006 6:40 PM
    Moderator
  • You're problem is more complicated than mine.  Let's hope someone from Microsoft can give us a definite answer on how to pass bound parameters to converters.  Meanwhile you may want to investigate MarkupExtensions.
    Monday, May 08, 2006 7:00 PM
  • The answer is straight-forward, but not what you want to hear.

    You can only target a binding at DependencyProperty on a DependencyObject. Binding does not inherit from DO, so you can't binding the converter parameter.

    If you want other state passed into a converter, you may have to subclass the desired obect and add new properties (as has been suggested).

    Monday, July 24, 2006 5:41 AM
  • ... or use MultiBinding
    • Proposed as answer by Aybe One Sunday, August 15, 2010 8:13 PM
    Friday, July 28, 2006 1:39 PM
  • ...oh yes...if all of the state you need already exists and is bind-able, MultiBinding is certainly better.

    Great catch.

    Friday, July 28, 2006 3:30 PM
  • Hi All,

        I'm very new to WPF, and need further help to pass some run-time value into the converter parameter.
       
        Basically i'm trying to add feature to the WPF DatePicker uploaded by Kevin Moore, to achieve something similar to the DatePicker in Vista.

        i.e: If user click on the CalendarTitle, it will ZoomOut such that the CalendarTitle now show "2008" and the CalendarItem now show the 12 months. I have also make changes to the MonthYearHeaderConverter such that it will show the different CalenderTitle based on different ConverterParameter

    e.g:   Different CalendarTitle based on different CurrentView
             MonthView:   July, 2008
             YearView:     2008
             DecadeView:  2000-2010
             CenturyView:  1900-2000
            
        e.g.

      

    public class CalendarTitle : ButtonBase     //Control , ICommandSource    

        { 

            //Do I needthis here? 

           //I already have an existing CurrentView in the MonthCalendar class 

          /**  public static DependencyProperty CurrentViewProperty =
                                       DependencyProperty.Register("CurrentView",

                                           typeof(CurrentView),
                                           typeof(CalendarTitle));



         

            public CurrentView CurrentView {

                get { return (CurrentView)GetValue(CurrentViewProperty); }

                set { SetValue(CurrentViewProperty, value); }

            }

            */ 

            /// <summary> 

            /// Static Constructor 

            /// </summary> 

            static CalendarTitle() 

            { 

                DefaultStyleKeyProperty.OverrideMetadata(typeof(CalendarTitle),
                                 
    new FrameworkPropertyMetadata(typeof(CalendarTitle)));            

            }       

        } 

     

     

     

    public sealed class MonthYearHeaderConverter : IValueConverter 

        { 

            /// <summary> 

            /// convert the month and year to a proper string 

            /// </summary> 

            /// <param name="value">DateTime</param> 

            /// <param name="targetType">string</param> 

            /// <param name="parameter">null</param> 

            /// <param name="culture">CultureInfo</param> 

            /// <returns>title string</returns> 

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

            { 

                if (value is DateTime) 

                { 

                    if (culture == null

                    { 

                        culture = CultureInfo.CurrentCulture; 

                    } 

     

                    if (culture.DateTimeFormat != null

                    { 

                        DateTime date = (DateTime)value; 

                        if (parameter is CurrentView) {                       

                            switch ((CurrentView)parameter) { 

                                case CurrentView.MonthView: 

                                    return date.ToString(
                                                       culture.DateTimeFormat.YearMonthPattern,
                                                       culture.DateTimeFormat);                                

                                case CurrentView.YearView: 

                                    return date.Year; 

                                    ..... 

                            } 

                        }else                    

                            return date.ToString(culture.DateTimeFormat.YearMonthPattern,
                                                         culture.DateTimeFormat); 

                        

                        

                    } 

                } 

     

                return String.Empty; 

            } 

     

    Thanks and Best Regards,

       
    Thursday, July 24, 2008 3:10 AM
  • You can also do this way:


    <TextBlock 
        Text="{Binding .,
            Mode=OneWay,
            Converter={StaticResource RemainingTimeConverter}}" />

    Passing to the binding path a 'Period', indicates that you will bind the entire object, an then on the converter you will have this object on the value parameter and will be able to acces all content that is in the current object being binded.

    hope this helps!

    Schneider
    • Edited by Schneider.Msdn Thursday, August 14, 2008 5:43 PM correction
    • Proposed as answer by Schneider.Msdn Thursday, August 14, 2008 5:44 PM
    Thursday, August 14, 2008 5:41 PM
  • Hi Schneider!

    Do you know any way ! To do the same with TemplateBinding

    <TextBlock x:Name="headerPartText"  Text="{TemplateBinding. ,  Converter={StaticResource textFormatConverter}}" Background="Transparent"/>


    I tried aforementioned syntax, but unable to make it work.

    Thanx in advance.

    Saime

    Engr.Saime Aley
    • Proposed as answer by Geoffrey Allen Wednesday, March 04, 2009 1:12 PM
    Thursday, September 11, 2008 11:14 AM
  •  Try using 'TemplateBinding .,' rather than 'TemplateBinding. ,'
    Wednesday, March 04, 2009 1:15 PM
  • I had a problem where I to wanted to do this.  I instead implemented a multivalue converter that took in the two values.

    so for your example you would write it like this.

    <TextBlock>
      <TextBlock.Text>
        <MultiBinding Converter="StaticResource RemainingTimeConverter}}" Mode="OneWay">
            <Binding Path=ElapsedTime />
            <Binding Path=TotalDuration />
        </MultiBinding>
      </TextBlock.Text>
    </TextBlock>

    Your RemainingTimeConverter would look like this

    class RemainingTimeConverter : IMultiValueConverter
        {
            #region IMultiValueConverter Members
            public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
            {
                //values[0] is emapsedTime
                //values[1] is totalduration
                throw new NotImplementedException();
            }
            public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
            #endregion
        }

     

    • Edited by odyth Monday, March 01, 2010 6:15 PM formating in chrome doesnt work
    • Proposed as answer by Art.Dan Tuesday, July 27, 2010 3:26 PM
    Monday, March 01, 2010 6:13 PM
  • I like the multi-value converter, offered by Odyth.   If you do not have the ability to composite the values, this would be the way to go.

    I was able to build a class-within-a-class (so I could composite my values) then pass in one binding value and cast it withing the converter.   In M-V-VM, that's the type of data-shaping we should be doing.

    My issue was the inability to databind the ConverterParameter, as it is a value type and only takes literals, ugh!

    I made my Converter work harder, by passing in a 'string literal' for the binding I was doing (BorderThickness or BorderBrush) and then using an Enum inside of my converter, and casting to it.

    This way I have a converter that can bind multiple values, needed for evaluation, and work for multiple scenarios.

    HighlightGridCell XAML Example

    A complete example, can be downloaded from:

    http://www.martymazurik.com/file.axd?file=2010%2f6%2fHighlightGridCell.zip.txt

    Saturday, June 12, 2010 2:54 PM
  • The value type that you pass into the IValueConverter does not have to match the type that is going to be returned by the converter.

    For example, I have a custom class (UserModel) that has a byte[] for the user's photo. If the length of the byte[] is 0, I want to show a silhouette instead of an empty image. I have two silhouettes. One for Male and one for Female. The UserModel has all the attributes needed to determine which photo to display.

    I just passed in the entire UserModel instance to the converter and it returns a byte[] based on the UserModel.

    Tuesday, August 31, 2010 7:27 PM
  • awesome, thanks!!!
    Tuesday, January 25, 2011 9:44 PM
  • @Schneider.Msdn
    thanks it works as you suggested :)
    Thursday, March 20, 2014 10:36 AM