WPF 进阶 格式化绑定的数据(数据转换,使用值转换器创建对象,应用条件格式化,评估多个属性,列表样式,包换复选框或单选按钮的ListBox控件,样式选择器,数据模板,更高级的模板,模板选择器)

22-31    集4.66h

1.数据转换

窗体绑定到集合的步骤:

(1)首先需要创建项的列表,这个项列表可在ItemsControI控件中显示。设置
DisplayMemberPath属性,指示希望为列表中的每个项显示的属性(或字段)。这个列表显示每一
项的型号名称:
<ListBOXNarne="1stProducts"Disp1ayMemberPath="Mode1Name"></ListBOX>
(2)用填充列表,将性设置为集合(或DataTabIe对象)。通常,当加载窗
口或用户单击按钮时,使用代码完成这一步骤。在本例中,ItemsControI控件被绑定到Product
对象的ObservabIeCoIIection集合。
(3)要显示项的特定信息,添加所需数量的元素,每个元素都有一个绑定表达式,用于确
定希望显示的属性或字段·在这个示例中,集合中的每个项都是Product对象。在下面的示例
中,通过绑定到Product.ModeINumber属性来显示项的型号:
<TextBoxText="{BindingPath=Mode1Number}"></TextBOx>
(4)将特定于项的元素连接到当前所选项的最简单方法是将它们封装到单个容器中。设置
容器的DataContext属性,以便引用在列表中选择的项:
<GridDataCOntext="{BindingE1ementName=1stProducts,Path=Se1ectedItem}">

字符串格式化。使用该功能可以通过设置Binding.StnngFormat属性对文本形式的数据
进行转换一一例如包含日期和数字的字符串。对于至少一半的格式化任务,字符串格式
化是一种便捷的技术。
值转换器:该功能更强大(有时更复杂),使用该功能可将任意类型的源数据转换为任意类
型的对象表示,然后可传递到关联的控件。

 

使用StringFormat属性:

当设置BindingStnngFormat属性时,使用标准的NET格式字符串,具体形式为{0:C}。其
中,0代表第一个数值,C引用希望应用的格式字符串一一一对于这个示例,它是标准的本地专
用的货币格式。在我们的计算机上,该格式将3.99转换为$3,99。整个表达式被包含到一对花括
号中。

Text={Bingding Path=UC ,StringFormat={}{0:C}}

为了转义字符串,需要在开始处使用稍微笨拙的花括号对。否则,XAML解析器可能会被{0:C}开头的花括号所迷惑。

只有当stnngFormat值以花括号开头时才需要{}转义序列

Text={BindingPath=UnitCost,StringEormat=The value is{O:C}.}">

为使用s亩ngFormat属性获得所希望的结果,需要合适的格式字符串·可以在Visualstudio
帮助文档中找到与所有格式字符串相关的内容。

值转换器是WPF数据绑定难题中非常有用的一部分。可通过如下几种有用的方式使用它们:
将数据格式化为字符串表示形式。例如,可将数字转换成货币字符串。这是值转换器最
明显的用途,但当然不是唯一用途。
创建特定类型的WPF对象。例如,可读取一一块二进制数据,并创建一幅能绑定到lmage
元素的BiunapImage对象。
根据绑定数据有条件地改变元素中的属性。例如,可创建值转换器,用于改变元素的背
景色以突出显示位于特定范围内的数值。

 

值转换器:

BindingStrmgFormat属性是针对简单的、标准的格式化数字和日期而创建的。

但许多数据绑定需要更强大的工具,称为值转换器(valueconverter)类。它负责在目标中

显示数据之前转换源数据,并且(对于双向绑定)在将数据应用回源之前转换新的目标值。

 

通过如下几种有用的方式使用它们:

将数据格式化为字符串表示形式。例如,可将数字转换成货币字符串。这是值转换器最
明显的用途,但当然不是唯一用途。
创建特定类型的WPF对象。例如,可读取一一块二进制数据,并创建一幅能绑定到lmage
元素的BiunapImage对象。
根据绑定数据有条件地改变元素中的属性。例如,可创建值转换器,用于改变元素的背
景色以突出显示位于特定范围内的数值。

 

使用值转换器设置字符串的格式:

为创建值转换器,需要执行以下4个步骤:
(1)创建一个实现了IValueConverter接口的类。
(2)为该类声明添加ValueConversion特性,并指定目标数据类型。
(3)实现convert()方法,该方法将数据从原来的格式转换为显示格式。
(4)实"ConvertBack()方法,该方法执行反向变换,将值从显示格式转换为原格式。

namespace DataBinding
{
    [ValueConversion(typeof(decimal), typeof(string))]
    public class PriceConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            decimal price = (decimal)value;
            return price.ToString("c", culture);
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            string price = value.ToString();
            
            decimal result;
            if (Decimal.TryParse(price, System.Globalization.NumberStyles.Any, culture, out result))
            {
                return result;
            }
            return value;
        }
    }


}
值转换器完整代码

为使用这个值转换器,首先需要将项目名称空间映射到能够在标记中使用的XML名称空间前
缀。下面例使用名称空间前缀,并假定值转换器位于Databing名称空间中:

xmlns:local="clr-namespace:DataBinding"

        <TextBox Margin="5" Grid.Row="2" Grid.Column="1">
          <TextBox.Text>
            <Binding Path="UnitCost">
              <Binding.Converter>
                <local:PriceConverter></local:PriceConverter>
              </Binding.Converter>              
            </Binding>
          </TextBox.Text>          
        </TextBox>

在许多情况下,可将相同的转换器用于多个绑定。在当前示例中,为每个绑定都创建一个

转换器实例是不合理的,而应当在Resources集合中创建转换器对象,之后,可绑定中使用

StaucResource引用来指向资源中的转换器对象.

运行效果

 

使用值转换器创建对象:

ProductImage字段包含文件名称,但不包含图像文件的完整路径,这样可灵活地将图像文件
放置到任何合适的位置。值转换器负责根据ProductImage字段和希望使用的目录创建指向图像
文件的URI,使用自定义的属性保存目录,该属性默认指向当前目录。

namespace DataBinding
{
    public class ImagePathConverter : IValueConverter
    {
        private string imageDirectory = Directory.GetCurrentDirectory();
        public string ImageDirectory
        {
            get { return imageDirectory; }
            set { imageDirectory = value; }
        }

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            string imagePath = Path.Combine(ImageDirectory, (string)value);
            return new BitmapImage(new Uri(imagePath)); 
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new NotSupportedException("The method or operation is not implemented.");
        }
    }
}
ImagePathConverter

使用转换器:

<window.Resources>
        <local :ImagePathConverter x:Key="ImagePathConverter"/>
</Window.Resources>
<Image Sourcce="{Binding Path=ProductImagePath,Converter={StaticResource ImagePathConverter}"/>

 

应用条件格式化:

设想希望通过不同的背景色标志那些价格高昂的产品项。使用下面的值转换器就能
方便地封装这一逻辑:

namespace DataBinding
{
    public class PriceToBackgroundConverter : IValueConverter
    {
        public decimal MinimumPriceToHighlight
        {
            get;
            set;
        }

        public Brush HighlightBrush
        {
            get;
            set;
        }

        public Brush DefaultBrush
        {
            get;
            set;
        }

        public object Convert(object value, Type targetType, object parameter,
          System.Globalization.CultureInfo culture)
        {
            decimal price = (decimal)value;
            if (price >= MinimumPriceToHighlight)
                return HighlightBrush;
            else
                return DefaultBrush;
        }

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


}
View Code

 

  <Window.Resources>
    <local:ImagePathConverter x:Key="ImagePathConverter"></local:ImagePathConverter>
    <local:PriceToBackgroundConverter x:Key="PriceToBackgroundConverter"
      DefaultBrush="{x:Null}" HighlightBrush="Orange" MinimumPriceToHighlight="10">      
    </local:PriceToBackgroundConverter>
  </Window.Resources>
 <Border 
      Background="{Binding Path=UnitCost, Converter={StaticResource PriceToBackgroundConverter}}" >
</Broder>

 

值转换器创建对象和条件格式化运行:

 

posted @ 2021-02-27 16:51  KnowledgePorter  阅读(114)  评论(0)    收藏  举报