使用資料繫結來傳輸資料

已完成

在此課程中,我們會探索如何使用資料繫結來進行資料輸入,根據應用程式的狀態來顯示和隱藏某些 UI 部分。 您也會熟悉完整的 INotifyPropertyChanged 模式。

讓我們使用看起來如下的親切問候語來擴充現有的示範。

Screenshot of sample app with a name entry field and submit button.

當您選取 [提交] 按鈕時,應用程式將會在頂端顯示一個簡單的問候語。

Screenshot of sample app showing

1. 開啟解決方案

如果您未在 Visual Studio 中開啟進行上一課時所建立的專案,請立即開啟。

2. 建立資料輸入 UI

資料輸入 UI 相當簡單:只是在畫面中間以單一水平配置顯示一個 TextBlock、一個 TextBox,以及一個 Button。 以水平方式放置控制項最簡單的方法,是使用 StackPanel,像這樣。

<StackPanel HorizontalAlignment="Center" 
            VerticalAlignment="Center" 
            Orientation="Horizontal">
    <TextBlock Margin="10" 
               VerticalAlignment="Center" 
               Text="Enter your name: "/>
    <TextBox Name="tbUserName" 
             Margin="10" 
             Width="150" 
             VerticalAlignment="Center"/>
    <Button Margin="10" 
            VerticalAlignment="Center" >Submit</Button>
</StackPanel>

請複製上述程式碼,並將它貼到 MainPage.xaml 的 Grid 標籤內,位於時鐘的 TextBlock 底下。

3. 實作並繫結 UserName 屬性

讓我們將注意力轉向程式碼。 開啟 MainPage.xaml.cs (您可以按 F7 來切換到程式碼後置,然後按 Shift+F7 來切換回 XAML)。 建立名為 UserName 的簡單屬性。

public string UserName { get; set; }

回到 MainPage.xaml 之後,我們可以在這個新建立的屬性與 TextBox 控制項之間建立資料繫結。 新增 Text 屬性來變更 TextBox 控制項,像這樣:

<TextBox Name="tbUserName" 
         Margin="10" 
         Width="150" 
         VerticalAlignment="Center" 
         Text="{x:Bind UserName, Mode=TwoWay}"/>

注意

在這裡,請勿混淆 TextBlockTextBox 控制項。 它們在 XAML 中看起來非常相似,但如果您將 UserName 繫結至 TextBlock 的文字屬性而不是 TextBox,則應用程式將無法運作。

透過上述程式碼,我們已在 TextBoxText 屬性與程式碼中的 UserName 屬性之間建立雙向繫結。 這意謂著每當使用者輸入文字 (並將焦點從 TextBox 移開) 時,程式碼中的 UserName 屬性都會變更。 此外,TextBox 的文字會在應用程式啟動時,或每當我們以 propertyName 參數 "UserName" 引發 NotifyPropertyChanged 事件時,設定成 UserName 中儲存的值。 (我們不會在此課程中這麼做)。

4. 建立 [Submit] (提交) 按鈕的 Click 處理常式

接著,在設計介面上,按兩下 [Submit] \(提交\) 按鈕。 這會自動在程式碼中建立並開啟 Button_Click 事件。 Button_Click 不是特別合適的名稱,因此請將方法名稱變更為更具表達性的 OnSubmitClicked。 當您完成輸入時,請按一下 OnSubmitClicked 行旁邊的燈泡。 從功能表選取 [將 'Button_Clicked' 重新命名為 'OnSubmitClicked']。 回到 XAML,確認按鈕的 XAML 現在看起來像這樣。

<Button Margin="10" 
        VerticalAlignment="Center" 
        Click="OnSubmitClicked">Submit</Button>

回到程式碼後置之後,讓我們在使用者按下按鈕時顯示簡單的對話方塊。 將下列程式碼加入 OnSubmitClicked 方法:

var dlg = new Windows.UI.Popups.MessageDialog($"Hello {UserName}!");
_ = dlg.ShowAsync();

如果您不熟悉 $"Hello {Username}" 語法,它相當於 "Hello " + UserName + "!"String.Format("Hello {0}!", UserName)。 這個更為精簡且易讀的功能被稱為字串內插補點,並已在 C# 6 中導入。

_捨棄變數。 它用來指出未使用 ShowAsync 方法的傳回值。 ShowAsync 方法會傳回 Task 物件,即是在未來要完成之工作的預留位置。 在我們的案例中,我們不需要等候工作完成,因此我們可以捨棄傳回值。

5. 執行應用程式

讓我們看看到目前為止已完成的部分! 按 F5 或 Ctrl-F5 來執行應用程式。 輸入您的名稱,選取 [Submit] \(提交\) 按鈕,應該會顯示問候您的對話方塊。

Screenshot of sample app with new greeting dialog box that displays

6. 實作 IsNameNeeded 屬性

如果您關閉對話方塊,系統仍然會顯示 UI 的名稱輸入部分。 這不是我們想要的效果。 我們需要在使用者成功填寫表單後隱藏表單。 讓我們在下一個步驟中使用資料繫結來執行此操作。

開啟 MainPage.xaml.cs,然後建立屬性以指出是否仍然需要輸入使用者的名稱。 在 MainPage 類別內新增下列程式碼:

private bool _isNameNeeded = true;

public bool IsNameNeeded
{
    get { return _isNameNeeded; }
    set
    {
        if (value != _isNameNeeded)
        {
            _isNameNeeded = value;
            PropertyChanged?.Invoke(
                this, new PropertyChangedEventArgs(nameof(IsNameNeeded)));
        }
    }
}

在到達 setter 之前,這是個具有支援欄位和 true 預設值的標準布林值屬性。 屬性 setter 會先確認新值是否與舊值相同。 如果相同,便不需要執行任何動作。 在沒有任何變更的情況下,您便不應該進行重新計算配置及重新呈現控制項的冗長程序。 不過,如果屬性的值「已經」變更,我們就必須使用 PropertyChanged 事件來告訴 UI 該狀況。

在上述程式碼中,您可以看到 INotifyPropertyChanged 介面的標準模式:

  • 請確認值是否已經變更。
  • 如果已變更,則設定新值。
  • 請通知 UI。

在通知 UI (假設繫結模式已設為 OneWayTwoWay) 之後,它會呼叫屬性的 getter,接收新值,然後相應地變更 UI。

7. 在使用者選取 [Submit] (提交) 按鈕後隱藏表單

在我們的案例中,我們想要讓名稱輸入表單只在使用者選取 [Submit] \(提交\) 按鈕前顯示。 然後它應該在顯示問候訊息時消失。 讓我們透過在開頭新增此程式碼來變更 OnSubmitClicked 方法:

if (string.IsNullOrEmpty(UserName))
{
    return;
}

IsNameNeeded = false;

首先,系統會執行快速檢查,因為這裡我們已不再接受空白使用者名稱。 輸入名稱之後,IsNameNeeded 會被設定為 false,且應用程式會接著顯示訊息對話方塊。 設定 IsNameNeeded 的值會引發 NotifyPropertyChanged 事件並通知 UI。

我們現在已完成用以隱藏 UI 的程式碼。 讓我們回到 XAML!

在 XAML 端,我們需要在 IsNameNeeded 為 False 時隱藏 TextBlockTextBoxButton。 或者,我們可以直接透過單一步驟隱藏其容器,StackPanel。 只需將 Visibility 屬性新增至 StackPanel 即可,像這樣:

Visibility="{x:Bind IsNameNeeded, Mode=OneWay}"

執行應用程式,在 TextBox 中輸入您的名稱,然後確認輸入表單在您選取 [Submit] \(提交\) 按鈕時會確實消失。

8. 使用 UI 對 UI 繫結來顯示問候語

讓我們將 MessageDialog 取代為更永久性的顯示項目:一個位於左上角的 TextBlock。 將一個新的 TextBlock 新增至 XAML 中的主要 Grid 控制項。

<TextBlock Text="{x:Bind sys:String.Format('Hello {0}!',  tbUserName.Text), Mode=OneWay}" 
           HorizontalAlignment="Left" 
           VerticalAlignment="Top" 
           Margin="10"/>

這裡有許多新項目正在進行。 讓我們仔細分析 Text 屬性的繫結!

為了評估 TextBlockText 屬性的值,系統會以格式字串 "Hello {0}" 呼叫內建的 String.Format 方法。 要格式化的物件將是 tbUserName.Text (亦即 tbUserName 控制項上的 Text)。 繫結的模式定義為 OneWay,表示 TextBlock 將從 TextBoxText 屬性接收資料。

這稱為「UI 對 UI 繫結」,因為資料繫結的來源和目標都在 UI 上。 若要查看其實際運作情況,您必須定義 sys 命名空間 (包含 System.Format 方法)。 將下列程式碼行新增至 XAML 中的根 Page 標籤:

xmlns:sys="using:System"

現在,如果您執行應用程式,就會看到每次按下按鍵時,問候語都會更新。 您甚至不需要將焦點從 TextBox 移開,或是選取 [Submit] \(提交\) 按鈕!

Screenshot of sample app running with a name entry field and value entered of

在真實世界的應用程式中,並不會透過 UI 對 UI 繫結顯示使用者的名稱。 您應該會繫結至 User 類別的 DisplayName 屬性或類似項目。

9. 隱藏問候語直到使用者選取 [提交] 為止

雖然在輸入時就更新問候語看起來很酷炫,但一開始出現的「Hello !」文字可能會看起來不專業。 建議讓問候語 TextBlock 保持隱藏,直到使用者選取 [提交] 按鈕後再顯示。

若要計算出是否要顯示問候語,請使用名為 GetGreetingVisibility 的方法,然後將它新增至 MainPage 類別。

public Visibility GetGreetingVisibility()
{
    return IsNameNeeded ? Visibility.Collapsed : Visibility.Visible;
}

您可能已注意到,當隱藏 StackPanel 時,我們是將 bool 值繫結至 Visibility 屬性 (其具有 UIElement.Visibility 的類型)。 將 Visibility 繫結至 bool 值的情況是如此常見,以致 Microsoft 在兩者間建立了預設轉換,這就是為何我們先前沒有收到任何類型轉換錯誤的原因。 不過,這個自動轉換只適用於屬性,因此 GetGreetingVisibility() 方法必須傳回 UIElement.Visibility,而不是布林值。

由於是搭配屬性,因此當我們希望 UI 重新評估該方法時,必須使用 PropertyChanged 事件來通知 UI。 因此,讓我們在 OnSubmitClicked 方法的結尾新增這一行。

PropertyChanged?.Invoke(this, 
    new PropertyChangedEventArgs(nameof(GetGreetingVisibility)));

作為最後一步,我們必須將 Visibility 屬性新增至問候語 TextBlock 來實際執行繫結。 在 MainPage.xaml 中,編輯 TextBlock,使其看來像這樣:

<TextBlock Text="{x:Bind sys:String.Format('Hello {0}!',  tbUserName.Text), Mode=OneWay}" 
           Visibility="{x:Bind GetGreetingVisibility(), Mode=OneWay}"
           HorizontalAlignment="Left" 
           VerticalAlignment="Top" 
           Margin="10"/>

請注意,我們不必為 GetGreetingVisibility() 呼叫新增任何命名空間參考,因為它本身是 MainPage 類別的成員。

最後,若要停止顯示 MessageDialog,請從 OnSubmitClicked 方法將下列行註解化。

// var dlg = new Windows.UI.Popups.MessageDialog($"Hello {UserName}!");
// dlg.ShowAsync();

現在您已準備就緒,可以執行應用程式並享有您的問候訊息。

摘要

在此課程中,您已了解資料繫結如何讓 UI 與您程式碼間或讓兩個 UI 間的資料傳輸變得更容易。 不過,要撰寫的連接程式碼為數眾多,尤其是在屬性 setter 中叫用 PropertyChanged 事件時。 在下一課中,您將建立一個協助程式類別,以簡化 INotifyPropertyChanged 模式的使用。

在此課程中,我們會探索如何使用資料繫結來進行資料輸入,根據應用程式的狀態來顯示和隱藏某些 UI 區段。 您也會熟悉完整的 INotifyPropertyChanged 模式,並深入了解 DataContext

讓我們使用看起來如下的親切問候語來擴充現有的示範。

Screenshot of sample app with a name entry field and submit button.

當您選取 [提交] 按鈕時,應用程式將會在頂端顯示一個簡單的問候語。

Screenshot of sample app showing

1. 建立與視窗同寬的 DataContext

如果您未在 Visual Studio 中開啟進行上一課時所建立的專案,請立即開啟。

在上一個課程中,我們已建立專用的 Clock 類別,且此類別已在顯示時鐘的 TextBlock 內具現化。 此 Clock 類別包含時鐘本身的商務邏輯。 不過,您通常必須因某些原因包含更多功能,而在 UI 上為每個單一控制項設定 DataContext 將非常乏味。

幸運的是,DataContext 的設計可套用到整個 XAML 樹狀結構 (或只套用到樹狀結構中的某個部分)。 DataContext 的一個重要屬性是它在整個 XAML 樹狀結構中繼承,您可以針對特定子樹狀結構覆寫它。

讓我們看看這在實務上如何運作。 建立名為 MainWindowDataContext 的新類別,並確定類別及其建構函式是公用的:

namespace DatabindingSampleWPF
{
    public class MainWindowDataContext
    {
        public MainWindowDataContext()
        {
        }
    }
}

現在,針對整個 Window,將此類別的執行個體設定為 DataContext。 在 MainWindow.xaml 中,在開頭 Window 標記正後方新增此項目:

<Window.DataContext>
    <local:MainWindowDataContext />
</Window.DataContext>

這時,Visual Studio 可能會指出不存在 DatabindingSampleWPF.MainWindowDataContext 類別。 這是因為自您新增此類別之後,並未編譯專案。 您可以透過組建專案來修正此錯誤。

讓我們複習截至目前為止已討論的內容。 DataContext 是設定於 Window (根) 層級。 此物件執行個體將會是 DataContext 內每個控制項的 Window。 唯一的例外是顯示時鐘的 TextBlock,它已設定自己的 DataContext,因此會覆寫繼承的全域 DataContext。 若此 TextBlock 在階層中有進一步的控制項,那些控制項也會繼承在 TextBlockDataContext 上設定的 Clock 物件。

2. 建立資料輸入 UI

資料輸入 UI 相當簡單:只是在畫面中間以單一水平配置顯示一個 TextBlock、一個 TextBox,以及一個 Button。 以水平方式放置控制項最簡單的方法,是使用 StackPanel,像這樣。

<StackPanel HorizontalAlignment="Center" 
            VerticalAlignment="Center" 
            Orientation="Horizontal">
    <TextBlock Margin="10" 
               VerticalAlignment="Center" 
               Text="Enter your name:"/>
    <TextBox Name="tbName" 
             Margin="10" 
             Width="150" 
             VerticalAlignment="Center"/>
    <Button Margin="10" 
            VerticalAlignment="Center">Submit</Button>
</StackPanel>

請複製上述程式碼,並將它貼到 MainPage.xaml 的 Grid 標籤內,位於時鐘的 TextBlock 底下。

3. 實作並繫結 UserName 屬性

讓我們將注意力轉向程式碼。 開啟 MainWindowDataContext.cs,然後建立名為 UserName 的新屬性。

public string? UserName { get; set; }

回到 MainWindow.xaml 之後,我們可以在 UserName 屬性與 TextBox 控制項之間建立資料繫結。 新增 Text 屬性來變更 TextBox 控制項,像這樣:

<TextBox Name="tbUserName" 
         Margin="10" 
         Width="150" 
         VerticalAlignment="Center" 
         Text="{Binding UserName, Mode=TwoWay}"/>

注意

在這裡,請勿混淆 TextBlockTextBox 控制項。 它們在 XAML 中看起來非常相似,但如果您將 UserName 繫結至 TextBlock 的文字屬性而不是 TextBox,則應用程式將無法運作。

透過上述程式碼,我們已在 TextBoxText 屬性與程式碼中的 UserName 屬性之間建立雙向繫結。 這意謂著每當使用者輸入文字 (並將焦點從 TextBox 移開) 時,程式碼中的 UserName 屬性都會變更。 此外,TextBox 的文字將會在應用程式啟動時,或每當我們以 propertyName 參數 "UserName" 引發 NotifyPropertyChanged 事件時,設定成 UserName 中儲存的值。 (我們不會在此課程中這麼做)。

注意

在 WPF 中,會自動為大部分的常見情況決定繫結模式。 例如,若您要繫結到 TextBoxText 屬性,WPF 預設會將繫結模式設定為 TwoWay。 這表示我們甚至可以略過這裡的指定繫結模式步驟,並只撰寫 Text={Binding UserName}。 您可以在這裡 \(機器翻譯\) 深入了解繫結模式。

4. 建立 [Submit] (提交) 按鈕的 Click 處理常式

接著,在設計介面上,按兩下 [Submit] \(提交\) 按鈕。 這會自動在 MainWindow.xaml.cs 中建立 Button_Click 事件並開啟檔案。 Button_Click 不是非常描述性的名稱,因此請將方法的名稱變更為 OnSubmitClicked。 在您完成輸入之後,請按一下 OnSubmitClicked 行旁邊的螺絲起子提示,然後從功能表中選取 [將 'Button_Clicked' 重新命名為 'OnSubmitClicked']。 回到 XAML,並確認按鈕的 XAML 現在看起來像這樣:

<Button Margin="10" 
        VerticalAlignment="Center" 
        Click="OnSubmitClicked">Submit</Button>

回到程式碼後置之後,讓我們在使用者按下按鈕時顯示簡單的對話方塊。 將便利屬性新增到 MainWindow 類別的頂端,以便我們可以輕鬆地存取設定為整個 MainWindowDataContextMainWindowDataContext 物件。

private MainWindowDataContext DC => (MainWindowDataContext)DataContext;

接下來,將下列程式碼新增至 OnSubmitClicked 方法:

MessageBox.Show($"Hello {DC.UserName}!");

TextBox 中輸入的文字值會儲存在 MainWindowDataContext.UserName 屬性中。 第一行會將對 MainWindowDataContext 物件的參考儲存在暫存變數中。 第二行會顯示包含問候訊息的訊息方塊。

如果您不熟悉 $"Hello {Username}" 語法,它相當於 "Hello " + UserName + "!"String.Format("Hello {0}!", UserName)。 這個更為精簡且易讀的語法被稱為字串內插補點,並已在 C# 6 中導入。

5. 執行應用程式

讓我們試用我們到目前為止所做的工作! 按 F5 或 Ctrl-F5 來執行應用程式。 輸入您的名稱,選取 [Submit] \(提交\) 按鈕,應該會顯示問候您的對話方塊。

Screenshot of sample app with new greeting dialog box that displays

6. 實作 IsNameNeeded 屬性

留意到在按下 [Submit] \(提交\) 按鈕之後,UI 的名稱輸入部分仍未消失。 我們需要在使用者成功填寫表單後隱藏它。 讓我們在下一個步驟中使用資料繫結來執行此操作。

首先,請開啟 MainWindowDataContext.cs,然後使 MainWindowDataContext 繼承自 INotifyPropertyChanged,和我們針對 Clock 類別所作的相同。

using System.ComponentModel;

public class MainWindowDataContext : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler? PropertyChanged;

接著,建立屬性以指出是否仍然需要輸入使用者的名稱。 在 MainWindowDataContext 類別內新增下列程式碼:

private bool _isNameNeeded = true;

public bool IsNameNeeded
{
    get { return _isNameNeeded; }
    set
    {
        if (value != _isNameNeeded)
        {
            _isNameNeeded = value;
            PropertyChanged?.Invoke(
                this, new PropertyChangedEventArgs(nameof(IsNameNeeded)));
        }
    }
}

在到達 setter 之前,這是個具有支援欄位和 true 預設值的標準布林值屬性。 屬性 setter 會先確認新值是否與舊值相同。 如果相同,便不需要執行任何動作。 在沒有任何變更的情況下,您便不應該進行重新計算配置及重新呈現控制項的冗長程序。 不過,如果屬性的值「已經」變更,我們就必須使用 PropertyChanged 事件來告訴 UI 該狀況。

在上述程式碼中,您可以看到 INotifyPropertyChanged 介面的標準模式:

  • 請確認值是否已經變更。
  • 如果已變更,則設定新值。
  • 請通知 UI。

在通知 UI (假設繫結模式已設為 OneWayTwoWay) 之後,它會呼叫屬性的 getter,接收新值,然後相應地變更 UI。

7. 在使用者選取 [Submit] (提交) 按鈕後隱藏表單

在我們的案例中,我們想要讓名稱輸入表單只在使用者選取 [Submit] \(提交\) 按鈕前顯示。 然後它應該在顯示問候訊息時消失。 讓我們透過在開頭新增此程式碼來變更 OnSubmitClicked 方法:

if (string.IsNullOrWhiteSpace(DC.UserName))
{
    return;
}

DC.IsNameNeeded = false;

首先,系統會執行快速檢查,因為這裡我們已不再接受空白使用者名稱。 輸入名稱之後,IsNameNeeded 會被設定為 false,且應用程式會接著顯示訊息對話方塊。 設定 IsNameNeeded 的值會引發 NotifyPropertyChanged 事件並通知 UI。

我們現在已完成用以隱藏 UI 的程式碼。 讓我們回到 XAML!

在 XAML 端,我們需要在 IsNameNeeded 為 False 時隱藏 TextBlockTextBoxButton。 或者,我們可以直接透過單一步驟隱藏其容器,StackPanel。 將 Visibility 屬性新增至 StackPanel,像這樣:

Visibility="{Binding IsNameNeeded, Converter={StaticResource BooleanToVisibilityConverter}}"

此繫結由兩個部分組成。 第一個部分指定繫結路徑,它指向設定為整個 WindowDataContextMainWindowDataContext 物件的 IsNameNeeded 屬性。

但是 IsNameNeeded 屬性是布林值,而 Visibility 的類型則是 System.Windows.Visibility \(機器翻譯\),其為 enum。 我們必須在兩者之間執行轉換。 這樣的轉換很常見,且 WPF 有名為 BooleanToVisibilityConverter 的內建協助程式類別。 我們必須建立此類別的執行個體,並從繫結宣告參照它。

我們會在 XAML 中具現化此類別,作為 Window 物件的資源。 每個 FrameworkElement 都可以有自己的資源集合,而且具有識別集合中每個資源的索引鍵。 上述繫結中的 BooleanToVisibilityConverter 就是此索引鍵,它會指向資源集合內的 BooleanToVisibilityConverter 物件。 您可以透過新增下列程式碼至 Window 開頭標記的正後方來定義資源集合:

<Window.Resources>
    <BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
</Window.Resources>

執行應用程式,在 TextBox 中輸入您的名稱,然後確認輸入表單在您選取 [Submit] \(提交\) 按鈕時會確實消失。

8. 使用 UI 對 UI 繫結來顯示問候語

讓我們將 MessageDialog 取代為更永久性的顯示項目:一個位於左上角的 TextBlock。 將一個新的 TextBlock 新增至 XAML 中的主要 Grid 控制項。

<TextBlock Text="{Binding Text, ElementName=tbName, StringFormat='Hello {0}!'}"
           HorizontalAlignment="Left" 
           VerticalAlignment="Top" 
           Margin="10"/>

這個新的 TextBlock 中引進了數個新內容。 讓我們仔細分析 Text 屬性的繫結!

為了評估 TextBlockText 屬性的值,系統會以格式字串 "Hello {0}" 呼叫內建的 String.Format 方法。 要格式化的物件將是 tbName.Text (亦即 tbName 控制項上的 Text)。 繫結的模式自動定義為 OneWay,表示 TextBlock 將從 TextBoxText 屬性接收資料。

這稱為「UI 對 UI 繫結」,因為資料繫結的來源和目標都在 UI 上。 若要以動作呈現,只要執行應用程式。 請注意與每個按鍵動作更新問候語的方式。 您甚至不需要將焦點從 TextBox 移開,或是選取 [Submit] \(提交\) 按鈕!

Screenshot of sample app running with a name entry field and value entered of

在真實世界的應用程式中,並不會透過 UI 對 UI 繫結顯示使用者的名稱。 您應該會繫結至 User 類別的 DisplayName 屬性或類似項目,或其他類似方法。

9. 隱藏問候語直到使用者選取 [提交] 為止

雖然在輸入時就更新問候語看起來很酷炫,但一開始出現的「Hello !」文字可能會看起來不專業。 建議讓問候語 TextBlock 保持隱藏,直到使用者選取 [提交] 按鈕後再顯示。

若要計算出是否要顯示問候語,請使用名為 GreetingVisibility 的屬性,然後將它新增至 MainWindowDataContext 類別。

public Visibility GreetingVisibility => IsNameNeeded ? Visibility.Collapsed : Visibility.Visible;

您也必須將 System.Windows 命名空間新增至 MainWindowDataContext 中的 using

您可能還記得之前當我們隱藏 StackPanel 時,我們是將 bool 值繫結至 Visibility 屬性 (其具有 System.Windows.Visibility 的類型)。 不過,如果繫結來源已經是正確的資料類型,我們便可以略過 BooleanToVisibilityConverter

如同以往,當我們希望 UI 重新評估 GreetingVisibility 時,必須使用 PropertyChanged 事件來通知 UI。 因此,讓我們將這一行加入到 IsNameNeeded setter 中 if 區塊的結尾。

PropertyChanged?.Invoke(
    this, new PropertyChangedEventArgs(nameof(GreetingVisibility)));

這可確保每當變更 IsNameNeeded 時,就會引發兩個 PropertyChanged 事件:一個用於 IsNameNeeded 屬性本身,而另一個用於計算屬性 GreetingVisibility (取決於 IsNameNeeded)。

作為最後一步,將 Visibility 屬性新增至問候語 TextBlock 來實際執行繫結。 在 MainWindow.xaml 中,編輯 TextBlock,使其如下所示:

<TextBlock Text="{Binding Text, ElementName=tbName, StringFormat='Hello {0}!'}"
           Visibility="{Binding GreetingVisibility}"
           HorizontalAlignment="Left" 
           VerticalAlignment="Top" 
           Margin="10"/>

最後,若要停止顯示 MessageBox,請從 MainWindow.xaml.cs 中的 OnSubmitClicked 方法將下列行註解化。

// MessageBox.Show($"Hello {DC.UserName}!");

現在您已準備就緒,可以執行應用程式並享有您的問候訊息。

摘要

在此課程中,您已了解資料繫結如何讓 UI 與您程式碼間或讓兩個 UI 間的資料傳輸變得更容易。 不過,要撰寫的連接程式碼為數眾多,尤其是在屬性 setter 中叫用 PropertyChanged 事件時。 在下一課中,您將建立一個協助程式類別,以簡化 INotifyPropertyChanged 模式的使用。