移动互联网(windows phone && windows 8 开发)

专著技术开发,成就美好未来
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一、      绑定(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       绑定到另一个元素的某个属性值。EgTextBoxAText目标数属性 绑定 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实现ConvertConvertBack方法。

  

View Code
 1  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
 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属性,ModeOneWay

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

 

View Code
  1 /// <summary>
  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         }

 

数据验证ValidationRuleSystem.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" };

        stk.DataContext = e;[l7] 

本例子中TextBox绑定了Employee中的RowNum属性,RowNumint型,当在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">

                        <Binding.ValidationRules>

                            <DataErrorValidationRule/>

                        </Binding.ValidationRules>[l8] 

                    </Binding>

                </TextBox.Text>

            </TextBox>

        </StackPanel>

 

Code

 

View Code
 1  public class Person : IDataErrorInfo[l9] 
 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      定义验证规则

 

View Code
 1  public class Validation : ValidationRule
 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(truenull);
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">

                        <Binding.ValidationRules>

                            <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>

 

  二、      WPF和之前的技术交互(WPF/WinForms)

 

System.Windows.Forms.Integration 命名空间提供实现常见互操作方案的类。 实现互操作功能的两个关键类是 WindowsFormsHost ElementHost

l         WPF 中承载 Windows Forms窗体控件

l         方法:

  wpf上承载Windows Forms控件,需要使用WindowsFormsHost。(添加System.Windows.FormsWindowsFormsIntegration程序集的引用。

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 里的内容与边框的之间的间隔。


 [l1]当前应用程序

 [l2]实体model’

 [l3]绑定到集合视图

 [l4]触发排序、分组

 [l5]注意的地方

 [l6]验证

 [l7]设置绑定源

 [l8]绑定验证

 [l9]实现这个接口

 [l10]使用自定义绑定