溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

什么是WPF之Binding表達(dá)式

發(fā)布時(shí)間:2020-07-13 15:35:57 來(lái)源:億速云 閱讀:414 作者:Leah 欄目:編程語(yǔ)言

今天就跟大家聊聊有關(guān)什么是WPF之Binding表達(dá)式,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結(jié)了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。

不管是定義控件還是用戶控件都會(huì)用到一個(gè)功能——綁定(Binding)。書面的叫法:元素綁定。意思就是讓綁定的元素實(shí)現(xiàn)數(shù)據(jù)同步。在筆者看來(lái)WPF引入這一個(gè)功能實(shí)在是太完美了。編程更加的具體化。特別是跟MVVM模式的配合,那叫完美。筆者不是學(xué)術(shù)派的。全面性的講述的話那是不現(xiàn)實(shí)。就從筆者的使用經(jīng)驗(yàn)來(lái)談Binding吧。

最普通的使用方式,他的目標(biāo)元素是控件上的DataContext對(duì)象。如下:

 <TextBlock Grid.Column="0" Text="{Binding DishName}" Style="{StaticResource TakingDishDishNameTextStyle}" />

DataContext這個(gè)屬性是在FrameworkElement類上面的。也就是說(shuō)大部分的控件上都會(huì)有自己的DataContext的。那么我們一般只有在最外層設(shè)置DataContext屬性。為了更加清楚的了解DataContext綁定。筆者做了一個(gè)簡(jiǎn)單的例子。筆者給最外面的Window設(shè)置了DataContext值。同時(shí)也給他的內(nèi)部的Grid也設(shè)置了DataContext值。但是他們倆個(gè)不是同一個(gè)對(duì)象類型只是屬性相同而以。如下

<Window x:Class="Wpf.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:aomi="http://aomiwpf.com/ModernUI"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local ="clr-namespace:Wpf"Title="MainWindow" Height="350" Width="525"><Window.DataContext><local:WindDataContext /></Window.DataContext><Grid><Grid.DataContext><local:GridDataContext /></Grid.DataContext><TextBlock Text="{Binding  TestName}"></TextBlock></Grid></Window>

執(zhí)行結(jié)果:

什么是WPF之Binding表達(dá)式

實(shí)驗(yàn)可以證明標(biāo)準(zhǔn)的綁定方式的目標(biāo)元素是DataContext。他會(huì)去找當(dāng)前綁定元素最接近的DataContext。我們?cè)趤?lái)一個(gè)假設(shè)——如果GridDataContext類里面屬性TestName換成TestName1的話,又是什么樣子呢?如下

 1 public class GridDataContext : NotifyPropertyChanged 2     { 3         private string _testName1 ="GridDataContext"; 4  5         public string TestName1 6         { 7             set 8             { 9 10                 if (this._testName1 != value)11                 {12                     this._testName1 = value;13                     OnPropertyChanged("TestName1");14                 }15             }16             get { return this._testName1; }17         }18     }

執(zhí)行結(jié)果:

什么是WPF之Binding表達(dá)式

不好意思!筆者以為他會(huì)去找Window的DataContext的屬性TestName。顯然他不會(huì)。又說(shuō)明了一點(diǎn),他只會(huì)去接近的DataContext里面找。不會(huì)一個(gè)直一個(gè)的往上面去找。

值得注意的是如果上面只是寫{Binding}的話,那就是把當(dāng)前的DataContext綁定過(guò)來(lái)。而不是他的屬性。

在開(kāi)發(fā)過(guò)程中,我們往往希望某個(gè)元素能跟另一個(gè)元素上面的屬性進(jìn)行綁定。只要另一個(gè)元素屬性改變就會(huì)通知某個(gè)元素一起改變。這個(gè)時(shí)候就是不得不用下面的方式來(lái)了。

{Binding ElementName=SomeThingName, Path=Text}

ElementName:表示元素的名稱。

Path:表示元素對(duì)象的屬性。

事實(shí)上我們可以想到一個(gè)問(wèn)題。綁定是不是只能一方影響一方呢。這就是綁定的里面要用到的模式。如下

{Binding ElementName=SomeThindName, Path=Text,Mode=TwoWay}

TwoWay:導(dǎo)致對(duì)源屬性或目標(biāo)屬性的更改可自動(dòng)更新對(duì)方。

OneWay: 當(dāng)綁定源(源)更改時(shí),更新綁定目標(biāo)(目標(biāo))屬性。

OneTime:當(dāng)應(yīng)用程序啟動(dòng)或數(shù)據(jù)上下文更改時(shí),更新綁定目標(biāo)。

OneWayToSource:當(dāng)目標(biāo)屬性更改時(shí)更新源屬性。

以上的用法算是比較常用的。也是比較簡(jiǎn)單的。不如讓我們看一下開(kāi)源項(xiàng)目里面的一個(gè)綁定表達(dá)式吧。如下

<Button Command="{Binding Source={x:Static SystemCommands.MinimizeWindowCommand}}" ToolTip="{x:Static modernui:Resources.Minimize}" Style="{StaticResource SystemButton}">
   <Button.Content>  <Grid Width="13" Height="12" RenderTransform="1,0,0,1,0,1"> <Path Data="M0,6 L8,6 Z" Width="8" Height="7" VerticalAlignment="Center" HorizontalAlignment="Center"  Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" StrokeThickness="2"  />  </Grid>
  </Button.Content></Button>

不知道大家看得明不明白。上面的意思是從父節(jié)點(diǎn)Button的Foreground和當(dāng)前Path的Stroke綁定在一起。主要的關(guān)鍵在AncestorType。用于指定父親的類型。Mode是一個(gè)RelativeSourceMode類型。他有四個(gè)值。如下。

PreviousData: 用于數(shù)據(jù)列表,意指以前的數(shù)據(jù)項(xiàng)。即是數(shù)據(jù)集合上面的顯示。不包括控件。

TemplatedParent:用于模板上的綁定。

Self:元素自己本身上的屬性相綁定。

FindAncestor:用于查找父級(jí)元素。

只要這樣子一講解就可以理解RelativeSource用于指定相對(duì)的源元素。即是目標(biāo)元素。

事實(shí)上,上面的表達(dá)式還有一種可能用到的寫法。即是多出了一個(gè)用于限制父級(jí)的深度(AncestorLevel)。如下

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}, AncestorLevel=2}, Path=Name}

注意:如果想對(duì)綁定的值進(jìn)行修改的話,要用轉(zhuǎn)化器。如下

{Binding ElementName=SomeThindName, Path=Text,Mode=TwoWay,Converter=XXXConverter}

在開(kāi)發(fā)自定義控件的時(shí)候,我們會(huì)經(jīng)常用到一個(gè)表達(dá)式。如下

  Width="{TemplateBinding Width}"

上面的寫法只是一種縮寫。完整的如下

 Width="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Width}"

可以說(shuō)上面的內(nèi)容是筆者最常用到的。接下來(lái)讓我們?cè)谌タ匆恍┙壎ㄆ渌膬?nèi)容點(diǎn)。即是那些不常見(jiàn)的內(nèi)容。

1.StringFormat的功能。相當(dāng)于string.format功能一樣子。舉個(gè)列子。如果我們要在金額的前加上“¥”的時(shí)候,可以用一下。如下

 <TextBlock Text="{Binding MoneyText, StringFormat=¥{0}}" />

如果不是這樣子做的話,你就不得不給“¥”一個(gè)TextBlock來(lái)顯示,或是MoneyText變成string類型,然后設(shè)置值里面加上¥。但是筆者這里卻是double類型的。所以用StringFormat的功能有就可以完美的決解了顯示“¥”的問(wèn)題。

執(zhí)行結(jié)果:

什么是WPF之Binding表達(dá)式

2.TargetNullValue的功能,用于綁定目標(biāo)是一個(gè)null值的時(shí)候,要顯示的內(nèi)容。如下筆者給NullName賦null。

 <TextBlock Text="{Binding NullName, TargetNullValue=aomi}" />

執(zhí)行結(jié)果:

什么是WPF之Binding表達(dá)式

3.FallbackValue的功能,用于綁定目標(biāo)是發(fā)生錯(cuò)誤的時(shí)候,要顯示的內(nèi)容。如下

<TextBlock Text="{Binding NullName, FallbackValue=aomi}" />

執(zhí)行結(jié)果筆者就不貼了。

文章最后。在來(lái)說(shuō)明一個(gè)不常用的功能——PriorityBinding。這個(gè)功能筆者不好說(shuō)。只能讓讀者們自行體會(huì)吧。他主要用于在加載時(shí)間比較多的時(shí)候,要顯示的信息。比如顯示“正在加載中...”。筆者做了例子吧。

Xaml:

<Window x:Class="Wpf.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:aomi="http://aomiwpf.com/ModernUI"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local ="clr-namespace:Wpf"Title="MainWindow" Height="350" Width="525"><Window.DataContext><local:MainViewModel /></Window.DataContext><Grid><TextBlock><TextBlock.Text><PriorityBinding><Binding Path="UserName" IsAsync="True"></Binding><Binding Path="LoadingName"></Binding></PriorityBinding></TextBlock.Text></TextBlock></Grid></Window>

ViewModel:

 public class MainViewModel : NotifyPropertyChanged
    {private string _userName ="Haya";private string _loadingName = "正在加載中...";public string UserName
        {set{if (this._userName != value)
                {this._userName = value;
                    OnPropertyChanged("UserName");
                }
            }get {
                Thread.Sleep(7000);return this._userName;
            }
        }public string LoadingName
        {set{if (this._loadingName != value)
                {this._loadingName = value;
                    OnPropertyChanged("LoadingName");
                }
            }get { return this._loadingName; }
        }
    }

執(zhí)行結(jié)果:

什么是WPF之Binding表達(dá)式

七秒后:

什么是WPF之Binding表達(dá)式

看完上述內(nèi)容,你們對(duì)什么是WPF之Binding表達(dá)式有進(jìn)一步的了解嗎?如果還想了解更多知識(shí)或者相關(guān)內(nèi)容,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝大家的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI