天天看點

WPF入門:資料綁定

原文: WPF入門:資料綁定

上一篇我們将 XAML 大概做了個了解 ,這篇将繼續學習WPF資料綁定的相關内容

資料源與控件的Binding

Binding

作為資料傳送UI的通道,通過

INotityPropertyChanged

接口的

PropertyChanged

事件通知

Binding

資料屬性發生改變

public class Product : INotifyPropertyChanged
  {
      private string name;
      public string Name
      {
          get { return name; }
          set
          {
              name = value;
              if (PropertyChanged != null)
              {
                  this.PropertyChanged.Invoke(this, new PropertyChangedEventArgs("Name"));
              }
          }
      }
      public event PropertyChangedEventHandler PropertyChanged;
  }           

通過Binding關聯UI控件元素

this.txtOfProduct.SetBinding(TextBox.TextProperty, new Binding() { Path = new PropertyPath("Name"), Source = p });           

控件之間的Binding

<TextBox x:Name="TextBox1" Text="{Binding ElementName=slider1,Path=Value,Mode=OneWay}"></TextBox>
 <Slider x:Name="slider1" Margin="5"></Slider>           
WPF入門:資料綁定

我們也可以通過背景C#代碼實作

TextBox1.SetBinding(TextBox.TextProperty, new Binding("Value") { ElementName = "slider1", Mode=BindingMode.OneWay });           

統計文本字元長度

<TextBox x:Name="TextBox1"  Margin="5"  TextWrapping="Wrap" ></TextBox>
 <TextBlock Margin="5"  TextAlignment="Right" Text="{Binding ElementName=TextBox1, Path=Text.Length}"></TextBlock>           
WPF入門:資料綁定

Binding的Path

Path的索引器方式

<TextBox x:Name="TextBox1"  Margin="5"  TextWrapping="Wrap" ></TextBox>
  <!--擷取Text的第三個字元-->
  <TextBlock Margin="5"  TextAlignment="Right" Text="{Binding ElementName=TextBox1, Path=Text.[2]}"></TextBlock>
  <TextBlock Margin="5"  TextAlignment="Right" Text="{Binding ElementName=TextBox1, Path=Text[2]}"></TextBlock>           

當使用一個集合或者

DataView

作為

Binding

源時,如果我們想把它的預設元素作為Path來使用

List<string> names = new List<string>() { "張三", "李四", "王五" };
 //張三
 this.TextBox1.SetBinding(TextBox.TextProperty, new Binding("/") { Source = names });
 //“張三”字元串的長度
 this.TextBox2.SetBinding(TextBox.TextProperty, new Binding("/Length") { Source = names,Mode=BindingMode.OneWay});
 //擷取“張三”字元串中的第1個字元
 this.TextBox3.SetBinding(TextBox.TextProperty, new Binding("/[0]") { Source = names, Mode = BindingMode.OneWay });           

如果集合中嵌套集合,我們依然可以通過多級"/"文法把子集作為Path的元素

class City
  {
      public string Name { get; set; }
  }

  class Province
  {
      public List<City> Citys { get; set; }
      public string Name { get; set; }
  }

  class Country
  {
      public List<Province> Provinces { get; set; }
      public string Name { get; set; }
  }           
TextBox1.SetBinding(TextBox.TextProperty, new Binding("/Name") { Source = countries });
  TextBox2.SetBinding(TextBox.TextProperty, new Binding("/Provinces/Name") { Source = countries });
  TextBox3.SetBinding(TextBox.TextProperty, new Binding("/Provinces/Citys/Name") { Source = countries });           
WPF入門:資料綁定

省略Path

sys

需要引用

xmlns:sys="clr-namespace:System;assembly=mscorlib"

<StackPanel.Resources>
     <sys:String x:Key="text">
         WPF入門手冊
     </sys:String>
 </StackPanel.Resources>
 <TextBox x:Name="TextBox1"  Margin="5" Text="{Binding .,Source={StaticResource ResourceKey=text}}" ></TextBox>           
TextBox2.SetBinding(TextBox.TextProperty, new Binding(".") { Source = "WPF技術入門" });           

沒有Path和Source,Binding可以通過DataContext擷取資料

<StackPanel.DataContext>
     <sys:String>
         WPF入門手冊
     </sys:String>
 </StackPanel.DataContext>
 <TextBox x:Name="TextBox1"  Margin="5" Text="{Binding Mode=OneWay}" ></TextBox>           

選中ListBox元素顯示對應的屬性的一個例子

<TextBox x:Name="TextBox1"  Margin="5" ></TextBox>
 <ListBox x:Name="ListBox1"></ListBox>           
List<City> cities = new List<City>() {
      new City() { Id=1,Name="北京" },
      new City() { Id=2,Name="昆明" },
      new City() { Id=3,Name="上海" },
      new City() { Id=4,Name="廈門" },
      new City() { Id=5,Name="廣州" }
  };

  this.ListBox1.ItemsSource = cities;
  this.ListBox1.DisplayMemberPath = "Name";
  this.TextBox1.SetBinding(TextBox.TextProperty, new Binding("SelectedItem.Id") { Source = this.ListBox1 });           
WPF入門:資料綁定

使用Binding的RelativeSource

Binding

有明确的資料源的時,我們可以通過

Soure

ElementName

指派辦法關聯

Binding

,但有事我們不知道

Soure

對象的名字是什麼,卻知道它與作為

Binding

目标對象的UI元素布局上的相對關系,通過

RelativeSourceMode

枚舉設定關聯的對象關系

<Grid x:Name="g1">
    <StackPanel x:Name="s1">
        <DockPanel x:Name="d1">
            <TextBox x:Name="TextBox1"  Margin="5" ></TextBox>
        </DockPanel>
    </StackPanel>
</Grid>           

背景代碼處理

RelativeSource rs = new RelativeSource(RelativeSourceMode.FindAncestor)
 {
     AncestorLevel = 1,
     AncestorType = typeof(StackPanel)
 };
 //将StackPanel的Name s1賦給了TextBox1的Text
 TextBox1.SetBinding(TextBox.TextProperty, new Binding("Name") { RelativeSource = rs });           

也可以通過XAML的方式指派

<Grid x:Name="g1">
        <StackPanel x:Name="s1">
            <DockPanel x:Name="d1">
                <TextBox x:Name="TextBox1"  Margin="5" Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type DockPanel},AncestorLevel=1,Mode=FindAncestor}, Path=Name}" ></TextBox>
            </DockPanel>
        </StackPanel>
    </Grid>           

Binding資料驗證

Binding

ValidationRules

屬性的類型為

Collection<ValidationRule>

。通過實作

Validate

方法傳回給

ValidationResult

對象,并設定

IsVaild

屬性,

ErrorContent

屬性可以接受一個字元串。

public class RangValidationRule : ValidationRule
 {
     //驗證資料
     public override ValidationResult Validate(object value, CultureInfo cultureInfo)
     {
         double d = 0;
         if (double.TryParse(value.ToString(), out d))
         {
             if (d >= 1 && d <= 100)
             {
                 return new ValidationResult(true, null);
             }
         }
         return new ValidationResult(false, "資料錯誤");
     }
 }           
<TextBox x:Name="TextBox1" Margin="5"></TextBox>
 <Slider x:Name="slider1" Minimum="1" Maximum="100" Margin="5"></Slider>           
Binding binding = new Binding("Value") {
     Source=slider1,
     UpdateSourceTrigger=UpdateSourceTrigger.PropertyChanged,
 };
 binding.ValidationRules.Add(new RangValidationRule());
 this.TextBox1.SetBinding(TextBox.TextProperty, binding);           
WPF入門:資料綁定

顯示錯誤提示

public MainWindow()
  {
      InitializeComponent();

      Binding binding = new Binding("Value")
      {
          Source = slider1,
          UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
          NotifyOnValidationError = true//開啟錯誤通知
      };
      binding.ValidationRules.Add(new RangValidationRule());

      this.TextBox1.SetBinding(TextBox.TextProperty, binding);
       //注冊驗證錯誤事件
      this.TextBox1.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(ValidationErrorNotify));
  }

  private void ValidationErrorNotify(object sender, RoutedEventArgs e)
  {
      var errors = Validation.GetErrors(this.TextBox1);
      if (errors.Count > 0)
      {
          TextBlock1.Text = errors[0].ErrorContent.ToString();
      }
  }           
WPF入門:資料綁定

多路Binding

一般我們在做注冊使用者功能的時候,輸入密碼的時候都需要再确認輸入密碼,比較兩次輸入是否一緻,現在我們可以通過多路Binding來簡單的實作這個功能

首先實作一個

IMultiValueConverter

接口功能,如果兩次密碼一緻,送出按鈕狀态為可用

public class SubmitMultiBindingConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            return (!values.Cast<string>().Any(a => string.IsNullOrEmpty(a))/*驗證所有元素非空*/ &&
                values[0].ToString() == values[1].ToString())/*值1=值2*/;
            
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }           

XAML代碼

<TextBox x:Name="Password" Margin="5"></TextBox>
 <TextBox x:Name="Passworder" Margin="5"></TextBox>
 <Button x:Name="Submit" Content="送出" Margin="10" Height="30" Width="100"></Button>           

背景Binding

Binding pwdBinding = new Binding("Text") { Source = Password };
 Binding pwderBinding = new Binding("Text") { Source = Passworder };
 MultiBinding multi = new MultiBinding() { Mode=BindingMode.OneWay};
 multi.Bindings.Add(pwdBinding);
 multi.Bindings.Add(pwderBinding);
 multi.Converter = new SubmitMultiBindingConverter();
 Submit.SetBinding(Button.IsEnabledProperty, multi);           
WPF入門:資料綁定

以上就是Binding常用到的功能,下篇我将繼續學習依賴屬性和WPF路由事件的相關内容