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?
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
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'
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
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();
}
}
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
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