8天入門wpf—— 第五天 數據綁定


     

       在webform中,如果提到“綁定”二字,相信大家都不會陌生,綁定,讓我們的代碼更加的簡潔優美,在wpf中也存在各種神馬的綁定,

當然使用上都是行隔理不隔。

     

一: 控件到控件的綁定

     既然是綁定,那么肯定就有”源對象“和”目標對象“兩種狀態實體,從圖的角度上來說存在三種狀態:

確實在wpf中存在這三種模式的對應方式,

1:OneWay

    正如圖A所說,Source影響着Target,但是Target卻影響不到Source。

2:OneWayToSource

   也正如圖B中所表述的一樣,Target影響Source,而Source卻影響不到Target。

3:TwoWay

   這個也就相當於無向圖的邊,Source與Target相互影響。

4:OneTime

   在OneWay的基礎上延伸了一個OneTime,僅綁定一次。如果大家屬性Jquery中的one函數我想就可以不用表述了。

 1 <Window x:Class="WpfApplication1.MainWindow"
 2          xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3          xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4          Title="MainWindow" Height="350" Width="525">
 5     <Canvas>
 6         <ScrollBar Height="24" Name="scrollBar1" Width="237" Orientation="Horizontal" Canvas.Left="103" Canvas.Top="51"  Minimum="1" Maximum="100" SmallChange="1" />
 7         <Label Canvas.Left="41" Canvas.Top="121" Content="OneWay" Height="28" Name="label1" />
 8         <TextBox Canvas.Left="165" Canvas.Top="121" Height="23"
 9                  Text="{Binding ElementName=scrollBar1, Path=Value, Mode=OneWay}"
10                  Name="textBox1" Width="120" />
11         <Label Canvas.Left="41" Canvas.Top="160" Content="OneWayToSource" Height="28" Name="label2" />
12         <TextBox Canvas.Left="165" Canvas.Top="160" Height="23"
13                    Text="{Binding ElementName=scrollBar1, Path=Value, Mode=OneWayToSource}"
14                  Name="textBox2" Width="120" />
15         <Label Canvas.Left="41" Canvas.Top="202" Content="TwoWay" Height="28" Name="label3" />
16         <TextBox Canvas.Left="165" Canvas.Top="202" Height="23"
17                    Text="{Binding ElementName=scrollBar1, Path=Value, Mode=TwoWay}"
18                  Name="textBox3" Width="120" />
19         <Label Canvas.Left="41" Canvas.Top="231" Content="OneTime" Height="28" Name="label4" />
20         <TextBox Canvas.Left="165" Canvas.Top="231" Height="23" 
21                    Text="{Binding ElementName=scrollBar1, Path=Value, Mode=OneTime}"
22                  Name="textBox4" Width="120" />
23     </Canvas>
24 </Window>

最終的結果,還是大家自己拖拖滾動條吧,有圖有真相。

 

二:.net對象與控件的綁定

     這種綁定還是經常使用的,在WebForm中我們常用的Eval就是此種綁定,因為俺從數據庫里好不容易撈了點數據總要呈現在UI上面吧,

好,不多說,上代碼說話。

 1 <Window x:Class="WpfApplication3.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:local="clr-namespace:WpfApplication3"
 5         Title="MainWindow" Height="350" Width="525">
 6     <Grid>
 7         <ListView  Height="287" HorizontalAlignment="Left" Margin="62,12,0,0" Name="listView1" VerticalAlignment="Top" Width="331">
 8             <ListView.View>
 9                 <GridView>
10                     <GridView.Columns>
11                         <GridViewColumn Header="姓名"  DisplayMemberBinding="{Binding Name}"/>
12                         <GridViewColumn Header="年齡" DisplayMemberBinding="{Binding Age}"/>
13                     </GridView.Columns>
14                 </GridView>
15             </ListView.View>
16         </ListView>
17     </Grid>
18 </Window>

 

首先謝天謝地,我們的數據出來了,好,現在我們有需求了,我現在需要給奇偶行填充不同底色,並且age=22的這行數據標紅,那在wpf中該

怎么做呢?我們依稀的記得在webform中我們會在“行事件”上做手腳,在數據的綁定上wpf給我們提供了一個口子,也就是在綁定時可以插入自

己的”事件處理代碼“,但必須要繼承自IValueConverter。

 1 <Window x:Class="WpfApplication3.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:local="clr-namespace:WpfApplication3"
 5         Title="MainWindow" Height="350" Width="525">
 6     <Window.Resources>
 7         <local:ColorConvert x:Key="myConvert"/>
 8         <Style x:Key="item" TargetType="{x:Type ListViewItem}">
 9             <Setter Property="Background">
10                 <Setter.Value>
11                     <Binding RelativeSource="{RelativeSource Self}" 
12 Converter="{StaticResource myConvert}"/>
13                 </Setter.Value>
14             </Setter>
15         </Style>
16     </Window.Resources>
17     <Grid>
18         <ListView ItemContainerStyle="{StaticResource ResourceKey=item}" Height="287" HorizontalAlignment="Left" Margin="62,12,0,0" Name="listView1" VerticalAlignment="Top" Width="331">
19             <ListView.View>
20                 <GridView>
21                     <GridView.Columns>
22                         <GridViewColumn Header="姓名"  DisplayMemberBinding="{Binding Name}"/>
23                         <GridViewColumn Header="年齡" DisplayMemberBinding="{Binding Age}"/>
24                     </GridView.Columns>
25                 </GridView>
26             </ListView.View>
27         </ListView>
28     </Grid>
29 </Window>
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Windows;
 6 using System.Windows.Controls;
 7 using System.Windows.Data;
 8 using System.Windows.Documents;
 9 using System.Windows.Input;
10 using System.Windows.Media;
11 using System.Windows.Media.Imaging;
12 using System.Windows.Navigation;
13 using System.Windows.Shapes;
14 
15 namespace WpfApplication3
16 {
17     /// <summary>
18     /// MainWindow.xaml 的交互邏輯
19     /// </summary>
20     public partial class MainWindow : Window
21     {
22         public MainWindow()
23         {
24             InitializeComponent();
25 
26             List<Student> list = new List<Student>();
27 
28             for (int i = 20; i < 30; i++)
29             {
30                 list.Add(new Student() { Name = "hxc" + i, Age = i });
31             }
32 
33             listView1.ItemsSource = list;
34         }
35     }
36 
37     public class ColorConvert : IValueConverter
38     {
39         public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
40         {
41             //這里的value既為當前的行對象
42             var item = value as ListViewItem;
43 
44             //獲取當前的item在當前的Listview中的位置
45             var view = ItemsControl.ItemsControlFromItemContainer(item) as ListView;
46 
47             var index = view.ItemContainerGenerator.IndexFromContainer(item);
48 
49             //當Age=22是紅色標示
50             if ((view.Items[index] as Student).Age ==22)
51                 return Brushes.Red;
52 
53             if (index % 2 == 0)
54                 return Brushes.Pink;
55             else
56                 return Brushes.Blue;
57         }
58 
59         public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
60         {
61             return null;
62         }
63     }
64 
65 
66     public class Student
67     {
68         public string Name { get; set; }
69 
70         public int Age { get; set; }
71     }
72 }

快看,效果出來了,這里要稍微解釋下IValueConverter的使用步驟:

①:自定義一個類繼承自IValueConverter,其中Convert方法的value 為綁定參數,parameter參數為綁定參數的附帶值。

1   public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)

②:我們需要在xaml中引用並寫入資源。

 1   <Window.Resources>
 2         <local:ColorConvert x:Key="myConvert"/>
 3         <Style x:Key="item" TargetType="{x:Type ListViewItem}">
 4             <Setter Property="Background">
 5                 <Setter.Value>
 6                     <Binding RelativeSource="{RelativeSource Self}" 
 7 Converter="{StaticResource myConvert}"/>
 8                 </Setter.Value>
 9             </Setter>
10         </Style>
11     </Window.Resources>

③:最后也就是在Binding中使用Convert,wpf在綁定數據的時候會自動調用我們自定義的myConvert方法。

 1   <Window.Resources>
 2         <local:ColorConvert x:Key="myConvert"/>
 3         <Style x:Key="item" TargetType="{x:Type ListViewItem}">
 4             <Setter Property="Background">
 5                 <Setter.Value>
 6                     <Binding RelativeSource="{RelativeSource Self}" 
 7 Converter="{StaticResource myConvert}"/>
 8                 </Setter.Value>
 9             </Setter>
10         </Style>
11     </Window.Resources>

 

三: .net方法與控件的綁定

    在做wpf時,有時我們需要在xaml中綁定.net中的方法,當然這在實際開發中也是很常用的,不過方法必要由ObjectDataProvider來封裝。

 1 <Window x:Class="WpfApplication5.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4         xmlns:local="clr-namespace:WpfApplication5"
 5         xmlns:sys="clr-namespace:System;assembly=mscorlib"
 6         Title="MainWindow" Height="350" Width="525">
 7     <Window.Resources>
 8         <ObjectDataProvider x:Key="Test" ObjectType="{x:Type local:Student}" MethodName="GetName">
 9         </ObjectDataProvider>
10     </Window.Resources>
11     <Grid>
12         <TextBlock Text="{Binding Source={StaticResource ResourceKey=Test}, Mode=OneWay}"/>
13     </Grid>
14 </Window>
 1 namespace WpfApplication5
 2 {
 3     /// <summary>
 4     /// MainWindow.xaml 的交互邏輯
 5     /// </summary>
 6     public partial class MainWindow : Window
 7     {
 8         public MainWindow()
 9         {
10             InitializeComponent();
11         }
12     }
13 
14     public class Student
15     {
16         //前台要引用的方法
17         public string GetName()
18         {
19             return "一線碼農";
20         }
21     }
22 }

 

四:wpf中的驗證

    我們知道不管在什么體系架構中都有屬於自己的一套驗證體系,比如webform中的驗證控件,mvc中的特性驗證,當然wpf也是有的,為了

驗證的靈活性,實際開發中我們用的比較多的還是”自定義驗證“,其實只需要實現ValidationRule接口就行了,然后寫上自定義的驗證邏輯。

 1 <Window x:Class="WpfApplication4.MainWindow"
 2         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4        xmlns:local="clr-namespace:WpfApplication4"
 5         Title="MainWindow" Height="350" Width="525">
 6     <Window.Resources>
 7         <local:Student x:Key="student"/>
 8     </Window.Resources>
 9     <Grid>
10         <TextBlock Height="23" HorizontalAlignment="Left" Margin="97,54,0,0" Name="textBlock1" Text="姓名" VerticalAlignment="Top" />
11         <TextBox DataContext="{StaticResource ResourceKey=student}" Height="23" HorizontalAlignment="Left" Margin="153,54,0,0" Name="textBox1" VerticalAlignment="Top" Width="120">
12             <TextBox.Text>
13                 <Binding Path="Name" UpdateSourceTrigger="PropertyChanged">
14                     <!-- 自定義的驗證規格,當然可以是多個Check -->
15                     <Binding.ValidationRules>
16                         <local:NameCheck />
17                     </Binding.ValidationRules>
18                 </Binding>
19             </TextBox.Text>
20             <TextBox.ToolTip>
21                 <!--將當前的錯誤信息顯示在tooltip上-->
22                 <Binding RelativeSource="{RelativeSource Self}"  Path="(Validation.Errors)[0].ErrorContent"/>
23             </TextBox.ToolTip>
24         </TextBox>
25     </Grid>
26 </Window>

 

 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Windows;
 6 using System.Windows.Controls;
 7 using System.Windows.Data;
 8 using System.Windows.Documents;
 9 using System.Windows.Input;
10 using System.Windows.Media;
11 using System.Windows.Media.Imaging;
12 using System.Windows.Navigation;
13 using System.Windows.Shapes;
14 
15 namespace WpfApplication4
16 {
17     /// <summary>
18     /// MainWindow.xaml 的交互邏輯
19     /// </summary>
20     public partial class MainWindow : Window
21     {
22         public MainWindow()
23         {
24             InitializeComponent();
25         }
26     }
27 
28     public class NameCheck : ValidationRule
29     {
30         public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)
31         {
32             var name = Convert.ToString(value);
33 
34             //如果名字長度大於4則是非法
35             if (name.Length > 4)
36                 return new ValidationResult(false, "名字長度不能大於4個長度!");
37 
38             return ValidationResult.ValidResult;
39         }
40     }
41 
42     public class Student
43     {
44         public string Name { get; set; }
45 
46         public int Age { get; set; }
47     }
48 }

 

同樣這里也需要注意的就是:

①   實現ValidationRule接口,重寫Validate方法,其中的邏輯,你懂的。

1 public override ValidationResult Validate(object value, System.Globalization.CultureInfo cultureInfo)

② 然后我們在需要驗證的控件上追加Rule驗證, 其中的UpdateSourceTrigger設定為字段改變時觸發,當然可選值有很多...

1   <TextBox.Text>
2                 <Binding Path="Name" UpdateSourceTrigger="PropertyChanged">
3                     <!-- 自定義的驗證規格,當然可以是多個Check -->
4                     <Binding.ValidationRules>
5                         <local:NameCheck />
6                     </Binding.ValidationRules>
7                 </Binding>
8             </TextBox.Text>

③ 最后要將實體寫入到驗證控件的DataContext上,最后大功告成。

1   <TextBox DataContext="{StaticResource ResourceKey=student}" Height="23" HorizontalAlignment="Left" Margin="153,54,0,0" Name="textBox1" VerticalAlignment="Top" Width="120">


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM