sábado, agosto 02, 2008

Value Converters - More Simple Samples

This is the third of several posts related to Value Converters. Reading the posts in order can be useful, but not necessary. The first post, Databinding 101, served as an intro to the problem and the second, DefaultValueConverter, introduced the basics about ValueConverters. Now we're ready to present several examples to give you more ideas of where ValueConverters can be used.

 

ImageSourceConverter

The Image control doesn't update its Source property automatically, so setting it to a path will work only the first time, but if the path in your datasource changes it won't be reflected, well the ImageSourceConverter will help you. This is really a bug that will be corrected in SL RTM, but meanwhile this is another place to use ValueConverters.

public class ImageSourceConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string path = (string)value;
return new BitmapImage(new Uri(path, UriKind.RelativeOrAbsolute));
}

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


VisibilityConverter



You might want to change the visibility of a control based on a boolean property of your objects, this is simple with the VisibiltyConverter:



public class VisibilityConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if ((bool)value)
return Visibility.Visible;
return Visibility.Collapsed;
}

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


StringFormatConverter



This is one of my favorites. ASP.NET and Winforms use a StringFormat that let you display properly numeric or date objects (use these cheat sheet as reference). With this converter for example you can simply pass the ConverterParameter of C to format a numeric value as currency and will work similar to the way it does in the mentioned platforms. This is another convertar that I feel should be part of the Binding object.



public class StringFormatConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string formatString = parameter.ToString();
return String.Format("{0:" + formatString + "}", value);
}

public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new InvalidOperationException("This Convert supports only OneWay binding");
}
}


StringFixedLengthConverter



For some controls you might want to specify a fixedlength for the text. You can do it with the StringFixedLengthConverter setting its ConverterParameter. This is rarely useful...



public class StringFixedLengthConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return GetFixedLengthText((string)value, int.Parse((string)parameter));
}

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

private string GetFixedLengthText(string originalString, int maxChars)
{
int textLength = originalString.Length;
if (textLength > maxChars)
return originalString.Substring(0, maxChars - 3) + "...";
int padding = (int)Math.Round((maxChars - textLength) / 2d);
string paddingChars = "";
for (int i = 0; i < padding; i++)
paddingChars += " ";
return paddingChars + originalString + paddingChars;
}
}


IfNullChangeColorConverter



This is not common, but we had run into cases where we need to change the color of a control in case a property is null. This could be combined with the DefaultValueConverter presented yesterday. Imagine you will display a DefaultValue of 'Not Available' if the person doesn't have a phone number, but you also want to greyout the text to emphasize the lack of data. To create this effect, specify the desired color in the ConverterParameter (if no value is specify grey will be used).



public class IfNullChangeColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null)
return new SolidColorBrush(GetColor(parameter));
return new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
}

public Color GetColor(object parameter)
{
byte[] argbColor = new byte[4];
if (parameter != null)
{
string[] argbColorStrings = parameter.ToString().Split(',');
for (int i = 0; i < 4; i++)
{
argbColor[i] = byte.Parse(argbColorStrings[i]);
}
}
else
{
//#FFC0C0C0
argbColor[0] = 255;
argbColor[1] = 192;
argbColor[2] = 192;
argbColor[3] = 192;
}
return Color.FromArgb(argbColor[0], argbColor[1], argbColor[2], argbColor[3]);
}

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


Creating ValueConverters is really easy and these examples are meant to show that, rather than to try to cover every scenario. However, ValueConverters have many drawbacks. You can't combine them (e.g. use StringFormat and DefaultValue for the same property because the binding object only allows one) and won't scale easily (you will end up with lots of classes for super simple scenarios). Tomorrow I will talk about a pattern that can overcome these drawbacks.



You can download the attached code here with the last examples and the classes presented here.


I format my code using Manoli's website


Don't forget to vote for your favorite topics for this column.

No hay comentarios.: