WPF 資料繫結詳解。。。
阿新 • • 發佈:2019-01-08
資料繫結
控制元件之間的繫結
繫結源 source 資料提供者
繫結物件 target 接受資料的物件,被繫結的物件
對 繫結物件 進行資料繫結,將其的屬性,和繫結源的某個屬性進行繫結
純 xaml 繫結
這裡面,TextBox 為繫結物件 ,他的 Text 屬性繫結 到 繫結源 Slider 的 Value 屬性上。只需要設定 繫結源 的 Element 和 Path 屬性的繫結
後臺繫結
這段程式碼,去掉 xaml 的繫結語法,後臺設定如下
前臺 xaml 和 後臺 資料物件繫結
xmal 屬性拓展和 後臺物件資料繫結
多級繫結
前臺多級資料繫結
集合繫結
ItemsSource 設定的時候,ListBox 裡面必須為空
如果 設定資料上下文,則前臺需要手動指定 itermsSource 繫結。當繫結為空的時候,其實就是繫結自身的 DataContent
集合繫結中,如果需要填寫 集合裡面的控制元件繫結,設定 itemsSource的時候,集合空間裡面必須是空的,也就是必須使用 資料模版
繫結型別轉換
繫結型別轉換需要實現一個 IValueConverter 的介面,裡面有兩個方法
前臺
將名字空間的 WpfAppTest 對映 到 ivalueconvert,然後將這個名稱空間下的 class boolToVisibily 寫入 StackPanel 的 Resources
然後 繫結物件 Image 設定 其 Visibility 屬性的繫結
{ Binding ElementName =ckbConImg, Path =IsChecked, Converter ={ StaticResource ResourceKey =ivalconvert}}
多向繫結
多向繫結 需要在 xaml 裡設定 mode 方式為 TwoWay。然後在繫結的資料來源的物件 繼承實現一個 INotifyPropertyChanged 。實現其 PropertyChanged 事件。在 PropertyChanged 事件中指定 繫結源的發生變化的屬性
原始碼下載 https://github.com/rsj217/WPFTest
控制元件之間的繫結
繫結源 source 資料提供者
繫結物件 target 接受資料的物件,被繫結的物件
對 繫結物件 進行資料繫結,將其的屬性,和繫結源的某個屬性進行繫結
純 xaml 繫結
< Grid > < TextBox Name ="tbxValue" Width ="100" Height ="30" Text ="{ Binding ElementName =slvolum, Path =Value}"></ TextBox > < Slider Name ="slvolum" Width ="105" Height ="20" Minimum ="1" Maximum ="100" Margin ="0,100,0,0"></ Slider > </ Grid >
這裡面,TextBox 為繫結物件 ,他的 Text 屬性繫結 到 繫結源 Slider 的 Value 屬性上。只需要設定 繫結源 的 Element 和 Path 屬性的繫結
後臺繫結
這段程式碼,去掉 xaml 的繫結語法,後臺設定如下
< Grid > < TextBox Name = "tbxValue" Width = "100" Height = "30" Text = "{ Binding ElementName =slvolum, Path =Value}" > < / TextBox > < Slider Name = "slvolum" Width = "105" Height = "20" Minimum = "1" Maximum = "100" Margin = "0,100,0,0" > < / Slider > < / Grid > public TDataBlind() { InitializeComponent(); Binding bding = new Binding (); // 設定繫結關係 bding.Source = slVolum; // 設定繫結源 bding.Path = new PropertyPath ( "Value" ); // 設定繫結屬性 tbxValue.SetBinding( TextBox .TextProperty, bding); // 新增幫頂關係和繫結物件 // tbxValue.SetBinding(TextBox.TextProperty, new Binding("Value") { Source = slVolum }); // 等價於上面的設定 }
前臺 xaml 和 後臺 資料物件繫結
< StackPanel > < TextBox Name ="tbName" Width ="100" Height ="30"></ TextBox > < TextBox x : Name ="tbAge" Width ="100" Height ="30"></ TextBox > </ StackPanel > public partial class TDataBlind : Window { public TDataBlind() { InitializeComponent(); Language lg = new Language () { Name = "python" , Age = 12 }; // 例項物件 Binding bdname = new Binding (); bdname.Source = lg; bdname.Path = new PropertyPath ( "Name" ); tbName.SetBinding( TextBox .TextProperty, bdname); // // tbName.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = lg }); Binding bdage = new Binding (); bdage.Source = lg; bdage.Path = new PropertyPath ( "Age" ); tbAge.SetBinding( TextBox .TextProperty, bdage); // // tbAge.SetBinding(TextBox.TextProperty, new Binding("Age") { Source = lg }); } } class Language { public string Name { get ; set ; } public int Age { get ; set ; } }
xmal 屬性拓展和 後臺物件資料繫結
< StackPanel Name ="stLanguage">
< TextBox Name ="tbName" Width ="100" Height ="30" Text ="{ Binding Name }"></ TextBox >
< TextBox x : Name ="tbAge" Width ="100" Height ="30" Text ="{ Binding Age }" ></ TextBox >
</ StackPanel >
public partial class TDataBlind : Window
{
public TDataBlind()
{
InitializeComponent();
Language lg = new Language () { Name = "python" , Age = 12 }; // 例項物件
stLanguage.DataContext = lg; // 設定資料上下文 (設定繫結)
}
}
class Language
{
public string Name { get ; set ; }
public int Age { get ; set ; }
}
多級繫結
< StackPanel >
< TextBox Name ="txtCountry" Width ="100" Height ="30"></ TextBox >
< TextBox Name ="txtProvince" Width ="100" Height ="30"></ TextBox >
< TextBox Name ="txtCity" Width ="100" Height ="30"></ TextBox > </ StackPanel >
public partial class TDataBlind : Window
{
public TDataBlind()
{
InitializeComponent();
City city = new City () { Name = "QingDao" };
Province province = new Province () { Name = "Shangdong" , CityList = new List < City > { city } };
Country country = new Country () { Name = "China" , ProvinceList = new List < Province > { province } };
txtCountry.SetBinding( TextBox .TextProperty, new Binding ( "Name" ) { Source = country });
txtProvince.SetBinding( TextBox .TextProperty, new Binding ( "Name" ) { Source = province });
txtCity.SetBinding( TextBox .TextProperty, new Binding ( "Name" ) { Source = city });
//txtCountry.SetBinding(TextBox.TextProperty, new Binding("Name") { Source = country }); // 表示 country 資料來源 下的 Name 屬性
//txtProvince.SetBinding(TextBox.TextProperty, new Binding("ProvinceList/Name") { Source = country }); // 表示 country 資料來源 下的 ProvinceList 下的 Name 屬性
//txtCity.SetBinding(TextBox.TextProperty, new Binding("ProvinceList/CityList/Name") { Source = country }); // 表示 country 資料來源 下的 ProvinceList 下的 CityList 下的 Name 屬性
}
}
class City
{
public string Name { get ; set ; }
}
class Province
{
public string Name { get ; set ; }
public List < City > CityList { get ; set ; }
}
class Country
{
public string Name { get ; set ; }
public List < Province > ProvinceList { get ; set ; }
}
前臺多級資料繫結
< StackPanel Name ="spCountry">
< TextBox Name ="txtCountry" Width ="100" Height ="30" Text ="{ Binding Name }"></ TextBox >
< TextBox Name ="txtProvince" Width ="100" Height ="30" Text ="{ Binding ProvinceList / Name}"></ TextBox >
< TextBox Name ="txtCity" Width ="100" Height ="30" Text ="{ Binding ProvinceList / CityList / Name}"></ TextBox >
</StackPanel >
City city = new City () { Name = "QingDao" };
Province province = new Province () { Name = "Shangdong" , CityList = new List < City > { city } };
Country country = new Country () { Name = "China" , ProvinceList = new List < Province > { province } };
spCountry.DataContext = country; // 資料上下文
集合繫結
ItemsSource 設定的時候,ListBox 裡面必須為空
<ListBox x:Name="lb" ItemsSource="{Binding}"></ListBox>
List<string> strlist = new List<string>{"python", "ruby", "lisp"};
lb.DataContent = strlist;
< ListBox x : Name ="lb"></ ListBox >
List < Language > strlist = new List < Language >();
strlist.Add( new Language () { Name = "python" , Age = 12 });
strlist.Add( new Language () { Name = "perl" , Age = 16 });
strlist.Add( new Language () { Name = "php" , Age = 14 });
lb.ItemsSource = strlist; // 設定繫結關係
lb.DisplayMemberPath = "Name" ; // 顯示繫結的屬性
如果 設定資料上下文,則前臺需要手動指定 itermsSource 繫結。當繫結為空的時候,其實就是繫結自身的 DataContent
< ListBox x : Name ="lb" ItemsSource ="{ Binding }"></ ListBox >
List < Language > strlist = new List < Language >();
strlist.Add( new Language () { Name = "python" , Age = 12 });
strlist.Add( new Language () { Name = "perl" , Age = 16 });
strlist.Add( new Language () { Name = "php" , Age = 14 });
lb.ItemsSource = strlist;
lb.DisplayMemberPath = "Name" ;
集合繫結中,如果需要填寫 集合裡面的控制元件繫結,設定 itemsSource的時候,集合空間裡面必須是空的,也就是必須使用 資料模版
< ListBox Name ="lb">
< ListBox.ItemTemplate >
< DataTemplate >
< StackPanel >
< TextBox Width ="100" Height ="30" Text ="{ Binding Name }"></ TextBox >
< TextBox Width ="100" Height ="30" Text ="{ Binding Age }"></ TextBox >
</ StackPanel >
</ DataTemplate >
</ ListBox.ItemTemplate >
</ ListBox >
List < Language > strlist = new List < Language >();
strlist.Add( new Language () { Name = "python" , Age = 12 });
strlist.Add( new Language () { Name = "perl" , Age = 16 });
strlist.Add( new Language () { Name = "php" , Age = 14 });
//lb.DataContext = strlist;
lb.ItemsSource = strlist;
繫結型別轉換
繫結型別轉換需要實現一個 IValueConverter 的介面,裡面有兩個方法
// 引數:
// value:
// 繫結源生成的值。
// targetType:
// 繫結目標屬性的型別。
// parameter:
// 要使用的轉換器引數。
// culture:
// 要用在轉換器中的區域性。
// 返回結果:
// 轉換後的值。 如果該方法返回 null,則使用有效的 null 值。
object Convert(object value, Type targetType, object parameter, CultureInfo culture);
// 引數:
// value:
// 繫結目標生成的值。
// targetType:
// 要轉換到的型別。
// parameter:
// 要使用的轉換器引數。
// culture:
// 要用在轉換器中的區域性。
// 返回結果:
// 轉換後的值。 如果該方法返回 null,則使用有效的 null 值。
object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
namespace WpfAppTest
{
/// <summary>
/// TDataConverter.xaml 的互動邏輯
/// </summary>
public partial class TDataConverter : Window
{
public TDataConverter()
{
InitializeComponent();
}
}
public class boolToVisibily : IValueConverter
{
public object Convert( object value, Type targetType, object parameter, System.Globalization. CultureInfo culture)
{
bool b = ( bool )value;
if (b)
{
return Visibility .Visible;
}
else
{
return Visibility .Hidden;
}
}
public object ConvertBack( object value, Type targetType, object parameter, System.Globalization. CultureInfo culture)
{
return true ;
}
}
}
前臺
< Window x : Class ="WpfAppTest.TDataConverter"
xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns : x ="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns : ivalueconvert ="clr-namespace:WpfAppTest"
Title ="TDataConverter" Height ="407" Width ="528">
< Grid >
< StackPanel >
< StackPanel.Resources >
< ivalueconvert : boolToVisibily x : Key ="ivalconvert" />
</ StackPanel.Resources >
< Image Name ="imgShow" Source ="media/free.png" Stretch ="None" Visibility ="{ Binding ElementName =ckbConImg, Path =IsChecked, Converter ={ StaticResource ResourceKey =ivalconvert}}"></ Image >
< CheckBox Name ="ckbConImg" Width ="30" Margin ="30"></ CheckBox >
</ StackPanel >
</ Grid > </ Window >
< Image Name = "imgShow"
Source = "media/free.png"
Stretch = "None"
Visibility = "{ Binding ElementName =ckbConImg, Path =IsChecked, Converter ={ StaticResource ResourceKey =ivalconvert}}" >
< / Image >
將名字空間的 WpfAppTest 對映 到 ivalueconvert,然後將這個名稱空間下的 class boolToVisibily 寫入 StackPanel 的 Resources
然後 繫結物件 Image 設定 其 Visibility 屬性的繫結
{ Binding ElementName =ckbConImg, Path =IsChecked, Converter ={ StaticResource ResourceKey =ivalconvert}}
多向繫結
多向繫結 需要在 xaml 裡設定 mode 方式為 TwoWay。然後在繫結的資料來源的物件 繼承實現一個 INotifyPropertyChanged 。實現其 PropertyChanged 事件。在 PropertyChanged 事件中指定 繫結源的發生變化的屬性
< StackPanel Name ="sp">
< TextBox Name ="txbName" Width ="100" Height ="30" Text ="{ Binding Name , Mode =TwoWay}"></ TextBox >
< Button Name ="btnShow" Width ="100" Height ="30" Click ="btnShow_Click"> show </ Button >
< Button Name ="btnShowName" Width ="100" Height ="30" Click ="btnShowName_Click"> btnShowName </ Button >
< Button Name ="btnChange" Width ="100" Height ="30" Click ="btnChange_Click"> change </ Button >
</ StackPanel >
public partial class TDatachanged : Window
{
Student lg = new Student () { Name = "python" }; // 設定資料上下文
public TDatachanged()
{
InitializeComponent();
sp.DataContext = lg;
}
private void btnShow_Click( object sender, RoutedEventArgs e)
{
MessageBox .Show(txbName.Text);
}
private void btnChange_Click( object sender, RoutedEventArgs e)
{
string time = DateTime .Now.Millisecond.ToString();
lg.Name = time;
MessageBox .Show(time);
}
private void btnShowName_Click( object sender, RoutedEventArgs e)
{
MessageBox .Show(lg.Name);
}
}
class Student : INotifyPropertyChanged // 繼承介面
{
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value ;
if (PropertyChanged != null ) // 如果 PropertyChanged 繫結關係發生
{
// 觸發 PropertyChanged 事件, 並監聽 繫結源物件的 變動屬性
PropertyChanged( this , new PropertyChangedEventArgs ( "Name" ));
}
}
}
public event PropertyChangedEventHandler PropertyChanged; // 宣告委託
}
原始碼下載 https://github.com/rsj217/WPFTest