Pass value of a field to Silverlight ConverterPara

2019-02-12 05:32发布

问题:

I'm writing my very first Silverlight app. I have a datagrid with a column that has two labels, for the labels, i am using an IValueConverter to conditionally format the data.

The label's "Content" is set as such:

Content="{Binding HomeScore, Converter={StaticResource fmtshs}}"

and

Content="{Binding AwayScore, Converter={StaticResource fmtshs}}"

The Convert method of my IValueConverter is such:

Public Function Convert(
  ByVal value As Object, 
  ByVal targetType As System.Type, 
  ByVal parameter As Object, 
  ByVal culture As System.Globalization.CultureInfo) As Object 
Implements System.Windows.Data.IValueConverter.Convert

    Dim score As Long = value, other As Long = parameter

    Return If(score < 0, "", 
        If(score - other > 5, (other + 5).ToString, score.ToString)
    )

End Function

So what i want to do is in the converter for HomeScore, i want to pass AwayScore to the ConverterParameter, and for AwayScore i want to pass the HomeScore to the converter. In the converter for either score i need to be able to know the value of the other score for formatting purposes.

But i cannot figure out the syntax for binding the ConverterParameter to another field.
I've tried the following:

Content="{Binding HomeScore, Converter={StaticResource fmtshs}, ConverterParameter=AwayScore}"  
Content="{Binding HomeScore, Converter={StaticResource fmtshs}, ConverterParameter={AwayScore}}"  
Content="{Binding HomeScore, Converter={StaticResource fmtshs}, ConverterParameter={Binding AwayScore}}"  

But none of those seem to work. How do i pass a field value to the ConverterParameter?

回答1:

As you can't pass anything but a literal into the ConverterParameter the solution is to pass the whole object into the converter and then you can access all of it's properties from within the Converter.

So your code becomes (assuming your object is called Match):

Public Function Convert(
  ByVal value As Object, 
  ByVal targetType As System.Type, 
  ByVal parameter As Object, 
  ByVal culture As System.Globalization.CultureInfo) As Object 
Implements System.Windows.Data.IValueConverter.Convert

    Dim match As Match = value

    ' Do stuff with match'

End Function

(Apologies for lack of detail in the code)

Then your XAML becomes

Content="{Binding Converter={StaticResource fmtshs}}"

NOTE While you are apparently binding directly to the converter, that's not actually the case. You are binding to the data context without specifying a Path so you can use access the whole thing.

Source



回答2:

Looks like you're trying to bind to a ConverterParameter which I'm afraid you can't. ConverterParameter can only take literal values e.g ConverterParameter='Your string'



回答3:

I had the same problem, and had to sleep on it. Seems the Converter gets "one shot" at getting the data - through the Binding value.

So make the Binding value a complex class. If you are using M-V-VM you should be data-shaping, anyway, so I made the Binding value 'work harder' by including the display value and the other data I needed in my converter (created a contained class if you will).

Next, I needed to have the Converter 'work harder', with its limitation of passing ConverterParameters as Value type literals, so I create an Enum in my converter, and cast the literal onto it for more elegancy in my Convert routine.

What I could do then is vary color (Brush) and thickness of a Grid cell, based on the value being displayed and another threshold value (that I check against).

The source code is on my blog site, its Silverlight 3 code using binding in a pseudo M-V-VM fashion (no dependency injection, but hey - its an example, right?)

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

then remove the .txt



回答4:

ChrisF has the only solution I've been able to come to - Bind the entire data object to content property and using a Converter built to expect this object type parse the properties you need in the converter itself.

<sdk:DataGridTextColumn Header="Report Name" Binding="{Binding Mode=OneTime, Converter={StaticResource ReportNameDateQuarterConverter}}" />


/// <summary>
/// Gets Exposure Report Name Quarter Number formatted from Report.Date and Report.Name
/// </summary>
public class ReportNameDateQuarterConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string qStr = "Quarter ";
        if (value != null && value.GetType() == typeof(Report))
        {
            switch (((Report)value).Date.Month)
            {
                case 1:
                case 2:
                case 3:
                    return qStr + "1 " + ((Report)value).Name;
                case 4: 
                case 5:
                case 6:
                    return qStr + "2 " + ((Report)value).Name;
                case 7:
                case 8:
                case 9:
                    return qStr + "3 " + ((Report)value).Name;
                case 10:
                case 11:
                case 12:
                    return qStr + "4 " + ((Report)value).Name;
                default:
                    return qStr + "? " + ((Report)value).Name;

            }
        }
        return qStr + "? " + ((Report)value).Name;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}


回答5:

Not totally sure I understand your problem but I think you're looking for binding with "elementname"?

ex: http://www.wintellect.com/CS/blogs/jprosise/archive/2009/03/27/silverlight-3-s-new-element-data-binding.aspx



回答6:

If you want to bind the converter parameter, have a look at this: http://brandontruong.blogspot.com/2009/06/binding-for-converter-parameter.html It may not be the cleanest solution, but it's simple and can be useful in some situations