Silverlight之StringFormat、IValueConverter
使用StringFormat属性进行格式化字符串:
在Silverlight中可以使用StringFormat(原理和ToString("格式",new CultureInfo("en-US"))一样)对字符串进行格式化,比如可以将字符串转换为小数、百分比、金钱格式等,也可以将字符串转换为指定的时间格式。
如果设置 Converter 和 StringFormat 属性,则会先对数据值应用转换器,然后应用 StringFormat。
当将 Binding 上的 StringFormat 设置为撰写字符串格式时,只能指定一个参数。
如果使用 MultiBinding(点击访问MSDN查看) 附加到单个绑定目标属性的 Binding 对象的集合,则仅当 StringFormat 属性是在 MultiBinding 上设置的时才应用此属性。 忽略在任何子 Binding 对象上设置的 StringFormat 的值。 撰写字符串格式中参数的数目不能超过 MultiBinding 中的子 Binding 对象数。
在使用 PriorityBinding(点击访问MSDN查看) 附加到单个绑定目标属性的 Binding 对象的集合,该属性从成功生成值的集合中的第一个绑定接收其值,可以在 PriorityBinding 和/或子绑定对象上设置 StringFormat。 如果 StringFormat 是在所应用的子绑定上设置的,则使用该值。 如果 StringFormat 不是在所应用的子绑定上设置的,则应用 PriorityBinding 的 StringFormat(如果已设置)。
例子1:
<TextBox Margin="5" Grid.Row="2" Grid.Column="1"
Text="{Binding UnitCost, StringFormat='C' }">
</TextBox>
将UnitCost属性的值转换为美元符号形式的
例子2:
<TextBlock Text="{Binding Date, StringFormat='0:MM/dd/yyyy' }"></TextBlock>
将Date属性的值转换为指定日期格式
下表格描述了 不同的StringFormat字符对应的转换结果:
--将字符串转换为数字格式:
Type Format String Example
Currency C $1,234.50.将字符串转换为美元格式
Scientific (Exponential) E 1.234.50E+004.
Percentage P 45.6%.转换为百分比
Fixed Decimal F? 依据设置在F后边的数字来决定保留几位小数,比如设置为F3则值为123.400. 设置为F0 则值为 123.
--将字符串转换为日期格式:
Type Format String Format
Short Date d M/d/yyyy 例子:: 10/30/2008
Long Date D dddd, MMMM dd, yyyy 例子: Wednesday, January 30, 2008
Long Date and Short Time f dddd, MMMM dd, yyyy HH:mm aa 例子: Wednesday, January 30, 2008 10:00 AM
Long Date and Long Time F dddd, MMMM dd, yyyy HH:mm:ss aa 例子: Wednesday, January 30, 2008 10:00:23 AM
ISO Sortable Standard s yyyy-MM-dd HH:mm:ss 例子: 2008-01-30 10:00:23
Month and Day M MMMM dd 例子: January 30
General G M/d/yyyy HH:mm:ss aa (依赖于电脑的设置) 例子: 10/30/2008 10:00:23 AM
可以看到使用StringFormat有很多局限性,并且是只能处理字符串的,所以需要提到IValueConverter接口。
使用IValueConvert三步骤:
1.创建一个实现于IValueConvert接口的类
2.实现Convert方法,该方法将数据源的值传递进来进行自定义的处理然后显示在Element
3.实现ConvertBack方法,该方法将Element的值发送给源时候进行处理
看下整个转换的过程
可以清楚的看到先从Property(对象属性),然后调用Convert方法,最后显示在Dependency控件的Property上;
然后当提交之后,调用ConvertBack方法发送到数据源对象去。
先看个Convert的例子(转换字符串):
可以看到代码挺简单的,先来分析下方法的参数
第一个就是转换的值(Convert的为源的值,ConvertBack的为目标控件的值),第二个为要转换的类型,第三个是要使用的转换参数,第四个是转换器中的区域性。
在Convert中对值进行了ToString的处理,进行转换为金钱格式的,然后返回,传入culture的原因是,不同区域的金钱格式是不同的。
在ConvertBack中调用Double.TryParse对目标控件的值进行转换尝试,如果为true,则转换并返回给源,否则返回原值。
记住,Parse方法和TryParse方法在IValueConvert中非常有用(因为在XAML提交到对象的时候要进行判断),且经常使用。
public class PriceConverter:IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
decimal price = decimal.Parse(value.ToString());
return price.ToString("C",culture);
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string price = value.ToString();
double result;
if (Double.TryParse(price,NumberStyles.Any,culture,out result ))
{
return result;
}
return value;
}
}
看下在XAML页面怎么使用:
首先在页面中引用当前IValueConvert的namespace
xmlns:binding="clr-namespace:ProSilverlight.DataBinding;assembly=ProSilverlight"
可以看到引用的格式 xmlns:前缀="clr-namespace:使用的类的命名空间;assemnbly=当前命名空间的程序集"
然后在Usercontrol(Page或者其他容器的Resource)的Resource中新建一个Convert的对象
<StackPanel.Resources>
<binding:PriceConverter x:Name="myPriceConvert"></binding:PriceConverter>
</StackPanel.Resources>
可以看到,在StackPanel.Resouces中创建了一个自定义Convert的实例,并且必须给Name属性赋值,因为需要通过Name属性访问此Convert。
最后在Binding中使用,设置Converter属性为{StaticResource myPriceConvert},因为当前的对象是在Resource中定义的。
<TextBox x:Name="txtPrice" Grid.Column="1" Text="{Binding Price,Mode=TwoWay, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True, Converter={StaticResource myPriceConvert}}" ></TextBox>
有时候我们希望根据字符串得到服务器端对应的图片,这个Converter也不复杂(在这里不仅仅是字符串操作了,而是其他任意的对象),代码如下:
在代码中通过HtmlPage.Document.DocumentUri得到当前运行网页(宿主所在)的地址,然后服务器端额根目录,最后在Convert中拼凑字符串地址,并返回ImagemapImage对象。
public class ImageConverter : IValueConverter
{
private string rootUri;
public string RootUri
{
get;
set;
}
public ImageConverter()
{
//得到当前网页的地址
string uri = HtmlPage.Document.DocumentUri.ToString();
//得到当前网页的根目录地址
rootUri = uri.Remove(uri.Length - uri.LastIndexOf('/'));
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
string imageUri = rootUri + "/" + value.ToString();
return new BitmapImage(new Uri(imageUri));
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return null;
}
}
通常来说我们会根据一个属性的值来改变元素的颜色,其实这个也很简单,代码如下:
可以看到,代码很简单的,定义MinimumPriceToHighlight属性,表示进行判断的值;HighLightBursh大于该条件的颜色(红色);DefaultBrush默认的颜色(白色).
在Convert中通过判断当前的value是否大于MinimumPriceToHighlight该条件值,来确定返回HighLightBursh还是DefaultBrush。
public class PriceToBackgroundConverter : IValueConverter
{
public double MinimumPriceToHighlight
{
get;
set;
}
public Brush HighLightBursh
{
get{return new SolidColorBrush(Colors.Red);}
set;
}
public Brush DefaultBrush
{
get{return new SolidColorBrush(Colors.White);}
set;
}
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
double price = (double)value;
if (price >= MinimumPriceToHighlight)
{
return HighLightBursh;
}
else
return DefaultBrush;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
当然里边的HighLightBursh和DefaultBrush可以在XAML中进行设置值的,如下:
<local:PriceToBackgroundConverter x:Key="PriceToBackgroundConverter"
DefaultBrush="{x:Null}" HighlightBrush="Orange" MinimumPriceToHighlight="50">
</local:PriceToBackgroundConverter>
可以看到,可以使用各种在控件中使用的赋值方式进行赋值,使用{x:Null}则返回未设置的颜色。
说了这么多都忽略了Convert的parameter参数,看下使用方法:
<TextBox Grid.Column="1" Text="{Binding Price,Mode=TwoWay, ValidatesOnNotifyDataErrors=True, NotifyOnValidationError=True, Converter={StaticResource myPriceConvert}, ConverterParameter=HighLight}" ></TextBox>
可以看到很简单,设置了ConverterParameter属性就好了,然后在Convert中就可以随意使用Parameter参数了。
好了,今天的介绍就到这里,如果大家有更好的使用方法多多交流。