注:一下内容及代码基本来自Charles Petzold著,蔡学庸译,电子工业出版社出版的《Windows Presentation Foundation 程序设计指南》一书
引言:在上一篇WPF: Binding(数据绑定)[上]中所提到的Binding,都是使用ElementName Property来设置数据源的,这一篇将叙述如何通过Binding的另外两个属性:Source和RelativeSource来设定绑定源(注意:这三个属性只能设置一个,否则会冲突),以及“如何让数据可以当作绑定源”和“如何在格式化转换源数据”
< StackPanel xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:g ="clr-namespace:System.Globalization;assembly=mscorlib" >
<!-- Bind ListBox ItemsSource to DayNames property of DateTimeFormatInfo. -->
< ListBox Name ="lstbox"
HorizontalAlignment ="Center"
Margin ="24"
ItemsSource ="{Binding
Source={x:Static g:DateTimeFormatInfo.CurrentInfo},
Path=DayNames,
Mode=OneTime}" />
<!-- Bind TextBlock Text to SelectedItem property of ListBox. -->
< TextBlock HorizontalAlignment ="Center"
Text ="{Binding ElementName=lstbox,
Path=SelectedItem, Mode=OneWay}" />
</ StackPanel >
以下是一个自定义的时间类型,继承自DenpendencyObject类:
// Define DependencyProperty.
public static DependencyProperty DateTimeProperty =
DependencyProperty.Register( " DateTime " , typeof (DateTime),
typeof (ClockTicker1));
// Expose DependencyProperty as CLR property.
public DateTime DateTime
{
set { SetValue(DateTimeProperty, value); }
get { return (DateTime) GetValue(DateTimeProperty); }
}
// Constructor sets timer.
public ClockTicker1()
{
DispatcherTimer timer = new DispatcherTimer();
timer.Tick += TimerOnTick;
timer.Interval = TimeSpan.FromSeconds( 1 );
timer.Start();
}
// Timer event handler sets DateTime property.
void TimerOnTick( object sender, EventArgs args)
{
DateTime = DateTime.Now;
}
代码说明:
1.
Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src="clr-namespace:Petzold.DigitalClock"
Title="Digital Clock"
SizeToContent="WidthAndHeight"
ResizeMode="CanMinimize"
FontFamily="Bookman Old Style"
FontSize="36pt">
< Window.Resources >
< src:ClockTicker1 x:Key="clock" />
</ Window.Resources >
< Window.Content >
< Binding Source="{StaticResource clock}" Path="DateTime" />
</ Window.Content >
</ Window >
if (PropertyChanged != null )
PropertyChanged( this ,
new PropertyChangedEventArgs( " DateTime " ));
具体实例
using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Threading;
namespace Petzold.FormattedDigitalClock
{
public class ClockTicker2 : INotifyPropertyChanged
{
// Event required by INotifyPropertyChanged interface.
public event PropertyChangedEventHandler PropertyChanged;
// Public property.
public DateTime DateTime
{
get { return DateTime.Now; }
}
// Constructor sets timer.
public ClockTicker2()
{
DispatcherTimer timer = new DispatcherTimer();
timer.Tick += TimerOnTick;
timer.Interval = TimeSpan.FromSeconds( 1 );
timer.Start();
}
// Timer event handler triggers PropertyChanged event.
void TimerOnTick( object sender, EventArgs args)
{
if (PropertyChanged != null ){
PropertyChanged( this,
new PropertyChangedEventArgs("DateTime " ));}
}
}
}
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace Petzold.FormattedDigitalClock
{
public class FormattedTextConverter : IValueConverter
{
public object Convert( object value, Type typeTarget,
object param, CultureInfo culture)
{
if (param is string )
return String.Format(param as string , value);
return value.ToString();
}
public object ConvertBack( object value, Type typeTarget,
object param, CultureInfo culture)
{
return null ;
}
}
}
在XAML文件中使用这个转换器。
< Window xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:src ="clr-namespace:Petzold.FormattedDigitalClock"
Title ="Formatted Digital Clock"
SizeToContent ="WidthAndHeight"
ResizeMode ="CanMinimize"
FontFamily ="Bookman Old Style"
FontSize ="36pt" >
< Window.Resources >
< src:ClockTicker2 x:Key ="clock" />
< src:FormattedTextConverter x:Key ="conv" />
</ Window.Resources >
< Window.Content >
< Binding Source ="{StaticResource clock}" Path ="DateTime"
Converter ="{StaticResource conv}"
ConverterParameter ="... {0:T} ..." />
</ Window.Content >
</ Window >
public class FormattedMultiTextConverter : IMultiValueConverter
{
public object Convert( object [] value, Type typeTarget,
object param, CultureInfo culture)
{
return String.Format((string )param, value);
}
public object [] ConvertBack( object value, Type[] typeTarget,
object param, CultureInfo culture)
{
return null ;
}
}
在XAML文件中使用:
< Window xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s ="clr-namespace:System;assembly=mscorlib"
xmlns:src ="clr-namespace:Petzold.EnvironmentInfo2"
Title ="Environment Info" >
< Window.Resources >
< src:FormattedMultiTextConverter x:Key ="conv" />
</ Window.Resources >
< TextBlock >
< TextBlock.Text >
< MultiBinding Converter =" {StaticResource conv} "
ConverterParameter =
"Operating System Version: {0}

.NET Version: {1}

Machine Name: {2}

User Name: {3}

User Domain Name: {4}

System Directory: {5}

Current Directory: {6}

Command Line: {7}" >
< Binding Source =" {x:Static s:Environment.OSVersion} " />
< Binding Source =" {x:Static s:Environment.Version} " />
< Binding Source =" {x:Static s:Environment.MachineName} " />
< Binding Source =" {x:Static s:Environment.UserName} " />
< Binding Source =" {x:Static s:Environment.UserDomainName} " />
< Binding Source =" {x:Static s:Environment.SystemDirectory} " />
< Binding Source =" {x:Static s:Environment.CurrentDirectory} " />
< Binding Source =" {x:Static s:Environment.CommandLine} " />
</ MultiBinding >
</ TextBlock.Text >
</ TextBlock >
</ Window >
代码说明:
(1). "
"为换行符
(2). 该代码通过x:Static获取本地计算机的静态信息,并分行打印
除了通过设置Binding的ElementName 和Source Property来设定绑定源,还有第三种选择:RelativeSource Property。它可以获取当前element及其祖先的有关数据
RelativeSource = {RelativeSource self}
RelativeSource = {RelativeSource AncestorType = {x:Type StackPanel}}
RelativeSource = {RelativeSource AncestorType = {x
:Type StackPanel}, AncestorLevel = 2 }
< StackPanel xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x ="http://schemas.microsoft.com/winfx/2006/xaml"
TextBlock.FontSize ="12" >
< StackPanel Orientation ="Horizontal"
HorizontalAlignment ="Center" >
< TextBlock Text ="This TextBlock has a FontFamily of " />
< TextBlock Text =" {Binding RelativeSource={RelativeSource self},
Path=FontFamily} " />
< TextBlock Text =" and a FontSize of " />
< TextBlock Text =" {Binding RelativeSource={RelativeSource self},
Path=FontSize} " />
</ StackPanel >
< StackPanel Orientation ="Horizontal"
HorizontalAlignment ="Center" >
< TextBlock Text ="This TextBlock is inside a StackPanel with " />
< TextBlock Text =
" {Binding RelativeSource={RelativeSource
AncestorType={x:Type StackPanel}},
Path=Orientation} " />
< TextBlock Text =" orientation" />
</ StackPanel >
< StackPanel Orientation ="Horizontal"
HorizontalAlignment ="Center" >
< TextBlock Text ="The parent StackPanel has " />
< TextBlock Text =
" {Binding RelativeSource={RelativeSource
AncestorType={x:Type StackPanel}, AncestorLevel=2},
Path=Orientation} " />
< TextBlock Text =" orientation" />
</ StackPanel >
</ StackPanel >
代码说明:
(1)第一个和第二个绑定分别获取当前TextBlock自己的字体类型和大小
(2)第二个绑定显示当前TextBlock所在的stackpanel的Orientation属性值
(3)第二个绑定显示当前TextBlock所在的stackpanel所在的stackpanel的Orientation属性值