学习WPF,转向移动互联网(windows phone && windows 8 )开发(下)
Posted on 2012-07-24 15:44 尊敬 阅读(1200) 评论(3) 编辑 收藏 举报一、 绑定(Binding )
定义
l 绑定是应用程序UI与业务逻辑之间建立连接的过程。
l 四个组件,绑定目标对象、目标属性、绑定源、绑定值的路径。
目标属性必须是依赖属性。建立绑定时,是将绑定目标绑定到绑定源,例如:使用数据绑定在Datagrid显示xml数据,就是将Datagrid绑定到xml数据。
绑定的数据流方向
1、 OneWay 绑定源属性值更改自动更新目标属性,目标属性值更改不会传播给绑定源属性(源—>UI)。
2、 TwoWay 绑定源更改更新目标属性,目标属性更改更新绑定源(源<—>UI)。
3、 OneWayToSource 与 OneWay 绑定相反;它在目标属性更改时更新源属性。 一个示例方案是您只需要从 UI 重新计算源值的情况(UI—>源)。。
4、 OneTime该绑定会导致源属性初始化目标属性,但不传播后续更改。此绑定类型实质上是 OneWay 绑定的简化形式,在源值不更改的情况下可以提供更好的性能(源—>UI(一次性))。
l 源值改变的时机由UpdateSourceTrigger控制,PropertyChanged即时改变,LostFocus目标对象失去焦点时改变,Explicit当应用程序调用 UpdateSource 时 改变(eg:提交时改变)。
指定绑定源的方法
u 绑定到另一个元素的某个属性值。Eg:TextBoxA的Text目标数属性 绑定 TextboxB对象,绑定值的路径Path=Text。使用ElementName绑定方法。
<TextBox Name="TextBoxA" ></TextBox>
<TextBox Name="TextBoxB" Text="{Binding ElementName=TextBoxA, Path=Text,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">
</TextBox>
u Source 属性是一种可以显式设置 Binding 的源和重写继承的数据上下文的方式。
Eg:现有一个string类型PersonName属性的Person对象。
<Window.Resources>
<src:Person x:Key="myDataSource" PersonName="Joe"/>
</Window.Resources>
<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}"/>
u RelativeSource。可以为目标对象指定绑定到其自身的其他属性,或者是其父元素的属性。在创建数据模板和控件模板、样式时使用。
Eg:在Datagrid的表格鼠标悬停时,使用Tooltip放大其表格的内容。
<Style TargetType="{x:Type uc:DataGridCell}">
<Setter Property="ToolTip" Value="{Binding Content.Text, RelativeSource={RelativeSource Self}}"/>
</Style>
u DataContext。将多个元素的属性绑定到同一个数据源时使用,在父元素的中设置,子元素继承之。
数据转换(默认转化器和自定义转换器)
集成接口IValueConverter实现Convert和ConvertBack方法。
2
3 {
4
5 int index = (int)value;
6
7 string result = null;
8
9 switch (index)
10
11 {
12
13 case 1:
14
15 result = "星期一";
16
17 break;
18
19 case 2:
20
21 result = "星期二";
22
23 break;
24
25 }
26
27 return result;
28
29 }
30
31 public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
32
33 {
34
35 string index = (string)value;
36
37 int result = -1;
38
39 switch (index)
40
41 {
42
43 case "星期一":
44
45 result = 1;
46
47 break;
48
49 case "星期二":
50
51 result = 2;
52
53 break;
54
55 }
56
57 return result;
58
59 }
绑定到集合
u 应使用ItemSource属性,Mode为OneWay。
u 设置动态绑定,集合的删除、插入操作可以自动更新UI,那集合必须实现INotifyPropertyChanged接口(此接口公开一个PropertyChangedEventHandler的事件,只要基础集合发生更改,都应该引发该事件)。WPF 提供 ObservableCollection<T>类,它是公开 INotifyCollectionChanged 接口的数据集合的内置实现。
u 集合视图
一旦 ItemsControl 绑定到数据集合,您可能希望对数据进行排序、筛选或分组。 若要执行此操作,可以使用集合视图,这是实现 ICollectionView 接口的类。
方法:定义个集合视图,在此视图上进行排序、筛选、分组的操作。绑定的目标对象绑定其集合视图。
XAML:
<!—资源-->
<Window.Resources>
<!—定义集合视图,大大提高集合的操作性-->
<CollectionViewSource Source="{Binding Source={x:Static Application.Current}[l1] , Path=Employee}" [l2]
x:Key="view"></CollectionViewSource>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<DataGrid Name="TestDg" AutoGenerateColumns="False" Grid.Row="0"
ItemsSource="{Binding Source={StaticResource view}[l3] }" IsReadOnly="True" >
<DataGrid.Columns>
<DataGridTextColumn Header="职工姓名" Binding="{Binding S_STUFFNAME}"></DataGridTextColumn>
<DataGridTextColumn Header="职工性别" Binding="{Binding Converter={StaticResource sexConverter}}"></DataGridTextColumn>
</DataGrid.Columns>
</DataGrid>
<StackPanel Grid.Row="1" Orientation="Vertical">
<CheckBox Name="sort" Checked="sort_Checked" Unchecked="sort_Unchecked" Content="sort"></CheckBox>
<CheckBox Name="group" Checked="group_Checked" Unchecked="group_Unchecked" Content="group"></CheckBox>[l4]
</StackPanel>
</Grid>
Code:
2
3 /// 集合视图
4
5 /// </summary>
6
7 CollectionViewSource datagridview;
8
9 public MainWindow()
10
11 {
12
13 InitializeComponent();
14
15 //获取XAML的view
16
17 datagridview = (CollectionViewSource)(this.Resources["view"]);
18
19 ObservableCollection<Employee> listEmy = new ObservableCollection<Employee>
20
21 {
22
23 new Employee(){ RowNum=1, S_STUFFCODE="00587000123", S_STUFFNAME="张三", S_SEX="1"},
24
25 new Employee(){RowNum=2,S_STUFFCODE="00587000124",S_STUFFNAME="李四",S_SEX="1"},};
26
27 //设置视图的Source
28
29 datagridview.Source = listEmy;
30
31 }
32
33 /// <summary>
34
35 /// 排序
36
37 /// </summary>
38
39 /// <param name="sender"></param>
40
41 /// <param name="e"></param>
42
43 private void sort_Checked(object sender, RoutedEventArgs e)
44
45 {
46
47 datagridview.SortDescriptions.Add(
48
49 new SortDescription("S_STUFFCODE", ListSortDirection.Descending));
50
51 datagridview.SortDescriptions.Add(
52
53 new SortDescription("S_STUFFNAME", ListSortDirection.Descending));
54
55 }
56
57 /// <summary>
58
59 /// 清除排序
60
61 /// </summary>
62
63 /// <param name="sender"></param>
64
65 /// <param name="e"></param>
66
67 private void sort_Unchecked(object sender, RoutedEventArgs e)
68
69 {
70
71 datagridview.SortDescriptions.Clear();
72
73 }
74
75 /// <summary>
76
77 /// 分组
78
79 /// </summary>
80
81 /// <param name="sender"></param>
82
83 /// <param name="e"></param>
84
85 private void group_Checked(object sender, RoutedEventArgs e)
86
87 {
88
89 PropertyGroupDescription group = new PropertyGroupDescription();
90
91 group.PropertyName = "S_SEX";
92
93 datagridview.GroupDescriptions.Add(group);
94
95 }
96
97 /// <summary>
98
99 /// 清除分组
100
101 /// </summary>
102
103 /// <param name="sender"></param>
104
105 /// <param name="e"></param>
106
107 private void group_Unchecked(object sender, RoutedEventArgs e)
108
109 {
110
111 datagridview.GroupDescriptions.Clear();
112
113 }
数据验证ValidationRule(System.Windows.Controls)
接受用户输入的大多数应用程序都需要具有验证逻辑,以确保用户输入了需要的信息。验证检查可以基于类型、范围、格式或其他应用程序特定的要求。
WPF内置的ValidationRule对象
u ExceptionValidationRule 检查在更新绑定源属性的过程中引发的异常
<StackPanel Grid.Row="2" Name="stk">
<TextBox Name="StartPriceEntryForm" Height="20" Width="150" DataContext="{Binding}"[l5] >
<TextBox.Text>
<Binding Path="RowNum" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<ExceptionValidationRule />
</Binding.ValidationRules>
</Binding>[l6]
</TextBox.Text>
</TextBox>
</StackPanel>
Code:
Employee e = new Employee() { RowNum = 1, S_STUFFCODE = "00587000123", S_STUFFNAME = "张三", S_SEX = "1" };
本例子中TextBox绑定了Employee中的RowNum属性,RowNum为int型,当在TextBox中输入的类型不是int类型时,就触发ExceptionValidationRule异常。
u DataErrorValidationRule表示一个规则,该规则检查由源对象的 IDataErrorInfo 实现所引发的错误。
<StackPanel Name="stkData" Grid.Row="3" >
<TextBox Height="20" Width="150" DataContext="{Binding}">
<TextBox.Text>
<Binding Path="Age" UpdateSourceTrigger="PropertyChanged">
<DataErrorValidationRule/>
</Binding.ValidationRules>[l8]
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
Code:
2
3 {
4
5 private int age;
6
7 public int Age
8
9 {
10
11 get { return age; }
12
13 set { age = value; }
14
15 }
16
17 public string Error
18
19 {
20
21 get
22
23 {
24
25 return null;
26
27 }
28
29 }
30
31 public string this[string name]
32
33 {
34
35 get
36
37 {
38
39 string result = null;
40
41
42
43 if (name == "Age")
44
45 {
46
47 if (this.age < 0 || this.age > 150)
48
49 {
50
51 result = "Age must not be less than 0 or greater than 150.";
52
53 }
54
55 }
56
57 return result;
58
59 }
60
61 }
62
63 }
自定义绑定验证
通过从ValidationRules类派生和实现Validate方法来创建自己的验证。
u 定义验证规则
2
3 {
4
5 public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
6
7 {
8
9 int age = Convert.ToInt32(value);
10
11 if (age > 150)
12
13 {
14
15 return new ValidationResult(false, "数字过大!");
16
17 }
18
19
20
21 return new ValidationResult(true, null);
22
23 }
24
25 }
u XAML中绑定
<StackPanel Name="stkData" Grid.Row="3" >
<TextBox Height="20" Width="150" DataContext="{Binding}">
<TextBox.Text>
<Binding Path="Age" UpdateSourceTrigger="PropertyChanged">
<local:Validation></local:Validation>
</Binding.ValidationRules>[l10]
</Binding>
</TextBox.Text>
</TextBox>
</StackPanel>
l 数据验证错误显示模板
当输入值无效时,需要在UI反馈用户。提供反馈的方法是将Validation.ErrorTempate附加属性中加入自定义的ControlTempate
<ControlTemplate x:Key="validationTemplate">
<DockPanel>
<TextBlock Foreground="Red" FontSize="20">!</TextBlock>
<AdornedElementPlaceholder/>
</DockPanel>
</ControlTemplate>
<ControlTemplate x:Key="validationTemplate">
<DockPanel>
<AdornedElementPlaceholder Name="MyAdorner"/>
<TextBox Foreground="Red" IsEnabled="False"
Text="{Binding ElementName=MyAdorner,
Path=AdornedElement.(Validation.Errors)[0].ErrorContent}">
</TextBox>
</DockPanel>
</ControlTemplate>
System.Windows.Forms.Integration 命名空间提供实现常见互操作方案的类。 实现互操作功能的两个关键类是 WindowsFormsHost 和 ElementHost
l 在 WPF 中承载 Windows Forms窗体控件
l 方法:
在wpf上承载Windows Forms控件,需要使用WindowsFormsHost。(添加System.Windows.Forms和WindowsFormsIntegration程序集的引用。
Eg:<Grid>
<WindowsFormsHost >
<wf:MaskedTextBox Height="20" BackColor="Red" Width="20" ></wf:MaskedTextBox>
</WindowsFormsHost>
</Grid>
l 限制
u Windows Forms控件不能调整大小,或者只能调整为特定的尺寸。
u Windows Forms控件不能旋转和扭曲。
l Windows Forms中使用Wpf
l 方法:
Windows Forms中使用Wpf,需要使用ElementHost。
三、 怎样布局一个漂亮的UI的?
l 项目总结
u 已有控件布局。界面统一风格(使用Blend绘出界面背景),使用样式、模板改变控件外观。
Eg:datagrid treeview
u 通过使用Blend软件,绘制自定义控件。
l 布局控件
l Canvas
Canvas比较简单,只是一个存储元素的容器,它不会自动调整内部元素的排列及大小。不指定元素位置,元素将默认显示在画布的左上方。Canvas的主要用途是用来画图。Canvas默认不会自动裁减超过自身范围的内容,即溢出的内容会显示在Canvas外面,这是因为默认 ClipToBounds="False";我们可以通过设置ClipToBounds="True来裁剪多出的内
l StackPanel
StackPanel就是将子元素按照堆栈的形式一一排列,通过设置面板的Orientation属性设置了两种排列方式:横排(Horizontal默认的)和竖排(Vertical)。
l WrapPanel
WrapPanel是一个非常简单的面板,从左至右按顺序位置定位子元素,如果排满断开至下一行。后续排序按照从上至下或从右至左的顺序进行。WrapPanel面板也提供了Orientation属性设置排列方式,这跟上面的StackPanel基本相似。不同的是WrapPanel会根据内容自动换行。
l DockPanel
DockPanel定义一个区域,在此区域中,您可以使子元素通过描点的形式排列。停靠面板其实就是在WinForm类似于Dock属性的元素。(随窗体缩放、扩大)
l Border
Border 是一个装饰的控件,此控件绘制边框及背景,在 Border 中只能有一个子控件(这个子控件又可以包含多个子控件)。Border 的几个重要属性:Background:用用一个 Brush 对象来绘制背景 ;BorderBrush:用一个Brush 对象来绘制边框 ;BorderThickness:此属性设置 Border 边框的大小;CornerRadius:此属性设置 Border 的每一个角圆的半径;Padding:此r属性设置 Border 里的内容与边框的之间的间隔。