XAML 控制項;繫結至一個 C++/WinRT 屬性XAML controls; bind to a C++/WinRT property

可有效地繫結至 XAML 控制項屬性稱為「可觀察的」屬性。A property that can be effectively bound to a XAML control is known as an observable property. 這個主意是以軟體設計模式為基礎稱為「觀察者模式」。This idea is based on the software design pattern known as the observer pattern. 本主題顯示在 C++/WinRT 中實作可觀察屬性,以及將 XAML 控制項繫結至這些屬性的方法 (如需背景資訊,請參閱資料繫結)。This topic shows how to implement observable properties in C++/WinRT, and how to bind XAML controls to them (for background info, see Data binding).

重要

如需一些基本概念和詞彙,以協助了解如何以 C++/WinRT 使用及撰寫執行階段類別,請參閱使用 C++/WinRT 來使用 API使用 C++/WinRT 撰寫 APIFor essential concepts and terms that support your understanding of how to consume and author runtime classes with C++/WinRT, see Consume APIs with C++/WinRT and Author APIs with C++/WinRT.

對一個屬性來說,可觀察的意義是什麼?What does observable mean for a property?

比方說一個名為 BookSku 的執行階段類別有個名為 Title 的屬性。Let's say that a runtime class named BookSku has a property named Title. 如果每當 Title 值變更,BookSku 就會引發 INotifyPropertyChanged::PropertyChanged 事件,表示 Title 是可觀察的屬性。If BookSku raises the INotifyPropertyChanged::PropertyChanged event whenever the value of Title changes, then that means that Title is an observable property. 它是 BookSku 的行為 (引發或不引發事件),判斷是哪一個,如果有的話,其屬性則為可觀察的。It's the behavior of BookSku (raising or not raising the event) that determines which, if any, of its properties are observable.

XAML 文字元素 (或控制項) 可以繫結至 (並處理) 這些事件。A XAML text element, or control, can bind to, and handle, these events. 這類元素或控制項處理事件的方式是:擷取更新的值,然後更新本身以顯示新的值。Such an element or control handles the event by retrieving the updated value(s), and then updating itself to show the new value.

注意

如需安裝和使用 C++/WinRT Visual Studio 延伸模組 (VSIX) 與 NuGet 套件 (一起提供專案範本和建置支援) 的資訊,請參閱 C++/WinRT 的 Visual Studio 支援For info about installing and using the C++/WinRT Visual Studio Extension (VSIX) and the NuGet package (which together provide project template and build support), see Visual Studio support for C++/WinRT.

建立空白的應用程式 (Bookstore)Create a Blank App (Bookstore)

請先在 Microsoft Visual Studio 中,建立新的專案。Begin by creating a new project in Microsoft Visual Studio. 建立 空白的應用程式 (C++/WinRT) 專案,並將它命名為 BookstoreCreate a Blank App (C++/WinRT) project, and name it Bookstore. 確定已取消核取 [將方案和專案放置於同一個目錄]。Make sure that Place solution and project in the same directory is unchecked. 以 Windows SDK 最新的正式推出版本 (即非預覽版本) 為目標。Target the latest generally-available (that is, not preview) version of the Windows SDK.

我們撰寫新的類別,代表擁有可觀察到標題屬性的一本書。We're going to author a new class to represent a book that has an observable title property. 我們在相同的編譯單位裡撰寫和使用此類別。We're authoring and consuming the class within the same compilation unit. 但是,我們希望能從 XAML 繫結至此類別,且基於這個原因,它會是一個執行階段類別。But we want to be able to bind to this class from XAML, and for that reason it's going to be a runtime class. 且我們會使用 C++/WinRT 撰寫和使用它。And we're going to use C++/WinRT to both author and consume it.

撰寫新執行階段類別的第一個步驟,要將一個新的 Midl 檔案 (.idl) 項目新增至專案。The first step in authoring a new runtime class is to add a new Midl File (.idl) item to the project. 將新項目命名為 BookSku.idlName the new item BookSku.idl. 刪除 BookSku.idl的預設內容,並在此執行階段類別宣告中貼上。Delete the default contents of BookSku.idl, and paste in this runtime class declaration.

// BookSku.idl
namespace Bookstore
{
    runtimeclass BookSku : Windows.UI.Xaml.Data.INotifyPropertyChanged
    {
        BookSku(String title);
        String Title;
    }
}

注意

您的檢視模型類別 — 事實上,您在應用程式中宣告的任何執行階段類別— 不需要衍生自基底類別。Your view model classes—in fact, any runtime class that you declare in your application—need not derive from a base class. 上面所宣告的 BookSku 類別是其範例。The BookSku class declared above is an example of that. 它會實作一個介面,但它不會衍生自任何基底類別。It implements an interface, but it doesn't derive from any base class.

您在從基底類別衍生的應用程式中宣告的任何執行階段類別,都稱為「可組合」類別。Any runtime class that you declare in the application that does derive from a base class is known as a composable class. 而且有以可組合的類別為主的條件約束。And there are constraints around composable classes. 若要讓應用程式通過 Visual Studio 和 Microsoft Store 所使用的 Windows 應用程式認證套件測試來驗證提交 (因而讓應用程式成功擷取到 Microsoft Store 中),可組合的類別必須最終衍生自 Windows 基底類別。For an application to pass the Windows App Certification Kit tests used by Visual Studio and by the Microsoft Store to validate submissions (and therefore for the application to be successfully ingested into the Microsoft Store), a composable class must ultimately derive from a Windows base class. 這表示位於繼承階層根目錄的類別必須是源自 Windows.* 命名空間的類型。Meaning that the class at the very root of the inheritance hierarchy must be a type originating in a Windows.* namespace. 如果您需要從基底類別衍生執行階段類別—例如,若要針對要衍生自的所有檢視模型實作 BindableBase 類別—則可衍生自 Windows.UI.Xaml.DependencyObjectIf you do need to derive a runtime class from a base class—for example, to implement a BindableBase class for all of your view models to derive from—then you can derive from Windows.UI.Xaml.DependencyObject.

檢視模型是檢視的抽取,所以會直接繫結至檢視 (XAML 標記)。A view model is an abstraction of a view, and so it's bound directly to the view (the XAML markup). 資料模型是資料的抽取,而且只能從您的檢視模型取用,並不會直接繫結至 XAML。A data model is an abstraction of data, and it's consumed only from your view models, and not bound directly to XAML. 因此,您可以宣告您的資料模型不是執行階段類別,而是 C++ 結構或類別。So you can declare your data models not as runtime classes, but as C++ structs or classes. 它們不需在 MIDL 中宣告,而且您可以隨意使用您喜歡的任何繼承階層。They don't need to be declared in MIDL, and you're free to use whatever inheritance hierarchy you like.

儲存檔案並建置專案。Save the file, and build the project. 建置尚未完全成功,但是會為我們執行一些必要的動作。The build won't entirely succeed yet, but it will do some necessary things for us. 特別是在建置程序期間,會執行 midl.exe 工具來建立 Windows 執行階段中繼資料檔案 (\Bookstore\Debug\Bookstore\Unmerged\BookSku.winmd),此檔案描述執行階段類別。Specifically, during the build process the midl.exe tool is run to create a Windows Runtime metadata file (\Bookstore\Debug\Bookstore\Unmerged\BookSku.winmd) describing the runtime class. 然後,執行 cppwinrt.exe 工具產生原始碼檔案在撰寫和使用執行階段類別中支援您。Then, the cppwinrt.exe tool is run to generate source code files to support you in authoring and consuming your runtime class. 這些檔案包含虛設常式,可協助您開始實作您在 IDL 中宣告的 BookSku 執行階段類別。These files include stubs to get you started implementing the BookSku runtime class that you declared in your IDL. 這些虛設常式為 \Bookstore\Bookstore\Generated Files\sources\BookSku.hBookSku.cppThose stubs are \Bookstore\Bookstore\Generated Files\sources\BookSku.h and BookSku.cpp.

以滑鼠右鍵按一下專案節點,然後按一下 [在檔案總管中開啟資料夾]。Right-click the project node and click Open Folder in File Explorer. 這會在檔案總管中開啟專案資料夾。This opens the project folder in File Explorer. 在那裏,從 \Bookstore\Bookstore\Generated Files\sources\ 資料夾將虛設常式檔案 BookSku.hBookSku.cpp 複製到專案資料夾中,也就是 \Bookstore\Bookstore\There, copy the stub files BookSku.h and BookSku.cpp from the \Bookstore\Bookstore\Generated Files\sources\ folder and into the project folder, which is \Bookstore\Bookstore\. 在 [方案總管] 中,選取專案資料夾後,確定 [顯示所有檔案] 已切換成開啟。In Solution Explorer, with the project node selected, make sure Show All Files is toggled on. 按一下滑鼠右鍵您複製的虛設常式檔案,然後按一下 [加入至專案]。Right-click the stub files that you copied, and click Include In Project.

執行 BookSkuImplement BookSku

現在要開啟 \Bookstore\Bookstore\BookSku.hBookSku.cpp,並實作我們的執行階段類別。Now let's open \Bookstore\Bookstore\BookSku.h and BookSku.cpp and implement our runtime class. 首先,您會在 BookSku.hBookSku.cpp 的頂端看到 static_assert,您必須將其移除。First, you'll see a static_assert at the top of BookSku.h and BookSku.cpp, which you'll need to remove.

然後,在 BookSku.h 中,進行下列變更。Next, in BookSku.h, make these changes.

  • 在預設的建構函式中,將 = default 變更為 = deleteOn the default constructor, change = default to = delete. 這是因為我們不想要預設的建構函式。That's because we don't want a default constructor.
  • 新增私人成員以儲存標題字串。Add a private member to store the title string. 請注意,我們使用的建構函式會採用 winrt::hstring 值。Note that we have a constructor that takes a winrt::hstring value. 此值是標題字串。That value is the title string.
  • 在標題變更時,為我們將引發的事件新增另一個私人成員。Add another private member for the event that we'll raise when the title changes.

進行這些變更之後,您的 BookSku.h 看起來像這樣。After making these changes, your BookSku.h will look like this.

// BookSku.h
#pragma once
#include "BookSku.g.h"

namespace winrt::Bookstore::implementation
{
    struct BookSku : BookSkuT<BookSku>
    {
        BookSku() = delete;
        BookSku(winrt::hstring const& title);

        winrt::hstring Title();
        void Title(winrt::hstring const& value);
        winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& value);
        void PropertyChanged(winrt::event_token const& token);
    
    private:
        winrt::hstring m_title;
        winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
    };
}
namespace winrt::Bookstore::factory_implementation
{
    struct BookSku : BookSkuT<BookSku, implementation::BookSku>
    {
    };
}

BookSku.cpp 中,如下實作函式。In BookSku.cpp, implement the functions like this.

// BookSku.cpp
#include "pch.h"
#include "BookSku.h"
#include "BookSku.g.cpp"

namespace winrt::Bookstore::implementation
{
    BookSku::BookSku(winrt::hstring const& title) : m_title{ title }
    {
    }

    winrt::hstring BookSku::Title()
    {
        return m_title;
    }

    void BookSku::Title(winrt::hstring const& value)
    {
        if (m_title != value)
        {
            m_title = value;
            m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Title" });
        }
    }

    winrt::event_token BookSku::PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
    {
        return m_propertyChanged.add(handler);
    }

    void BookSku::PropertyChanged(winrt::event_token const& token)
    {
        m_propertyChanged.remove(token);
    }
}

Title 更動子函式裡,我們檢查是否設定了與目前值不同的值。In the Title mutator function, we check whether a value is being set that's different from the current value. 如果是,則更新標題並使用與變更過的屬性名稱相同的引數引發 INotifyPropertyChanged::PropertyChanged 事件。And, if so, then we update the title and also raise the INotifyPropertyChanged::PropertyChanged event with an argument equal to the name of the property that has changed. 這是為了讓使用者介面 (UI) 知道要重新查詢哪些屬性的值。This is so that the user-interface (UI) will know which property's value to re-query.

現在,如果您去檢查,會發現專案已重新建置。The project will build again now, if you want to check that.

宣告和實作 BookstoreViewModelDeclare and implement BookstoreViewModel

我們的主要 XAML 頁面會繫結至主要檢視模型。Our main XAML page is going to bind to a main view model. 且檢視模型會有幾個屬性,包括類型之一的 BookSkuAnd that view model is going to have several properties, including one of type BookSku. 在此步驟,我們會宣告並實作主要檢視模型執行階段類別。In this step, we'll declare and implement our main view model runtime class.

新增一個 Midl 檔案 (.idl) 項目名為 BookstoreViewModel.idlAdd a new Midl File (.idl) item named BookstoreViewModel.idl. 另請參閱將執行階段類別分解成 Midl 檔案 (.idl)But also see Factoring runtime classes into Midl files (.idl).

// BookstoreViewModel.idl
import "BookSku.idl";

namespace Bookstore
{
    runtimeclass BookstoreViewModel
    {
        BookstoreViewModel();
        BookSku BookSku{ get; };
    }
}

儲存並建置 (建置尚未完全成功,但是我們此時建置就是為了再次產生 stub 檔案)。Save and build (the build won't entirely succeed yet, but the reason we're building is to generate stub files again).

Generated Files\sources 資料夾將 BookstoreViewModel.hBookstoreViewModel.cpp 複製到專案資料夾,在專案中包含它們。Copy BookstoreViewModel.h and BookstoreViewModel.cpp from the Generated Files\sources folder into the project folder, and include them in the project. 開啟那些檔案 (再次移除 static_assert),並實作執行階段類別,如下所示。Open those files (removing the static_assert again), and implement the runtime class as shown below. 請注意,我們在 BookstoreViewModel.h 中如何宣告 BookSku.h,其會宣告 BookSku 的實作類型 (也就是 winrt::Bookstore::implementation::BookSku)。Note how, in BookstoreViewModel.h, we're including BookSku.h, which declares the implementation type for BookSku (which is winrt::Bookstore::implementation::BookSku). 我們會從預設的建構函式中移除 = defaultAnd we're removing = default from the default constructor.

注意

在下面的 BookstoreViewModel.hBookstoreViewModel.cpp 中,程式碼闡述了建構 m_bookSku 資料成員的預設方式。In the listings below for BookstoreViewModel.h and BookstoreViewModel.cpp, the code illustrates the default way of constructing the m_bookSku data member. 這是從第一版 C++/WinRT 就開始使用的方法,您最好至少要熟悉此模式。That's the method that dates back to the first release of C++/WinRT, and it's a good idea to be at least familiar with the pattern. 到了 C++/WinRT 2.0 版和更新的版本,有一套已經最佳化的建構方法可供您使用,稱為「統一結構」 (請參閱 C++/WinRT 2.0 中的新聞和變更)。With C++/WinRT version 2.0 and later, there's an optimized form of construction available to you known as uniform construction (see News, and changes, in C++/WinRT 2.0). 稍後在本主題中,我們將示範統一建構的範例。Later in this topic, we'll show an example of uniform construction.

// BookstoreViewModel.h
#pragma once
#include "BookstoreViewModel.g.h"
#include "BookSku.h"

namespace winrt::Bookstore::implementation
{
    struct BookstoreViewModel : BookstoreViewModelT<BookstoreViewModel>
    {
        BookstoreViewModel();

        Bookstore::BookSku BookSku();

    private:
        Bookstore::BookSku m_bookSku{ nullptr };
    };
}
namespace winrt::Bookstore::factory_implementation
{
    struct BookstoreViewModel : BookstoreViewModelT<BookstoreViewModel, implementation::BookstoreViewModel>
    {
    };
}
// BookstoreViewModel.cpp
#include "pch.h"
#include "BookstoreViewModel.h"
#include "BookstoreViewModel.g.cpp"

namespace winrt::Bookstore::implementation
{
    BookstoreViewModel::BookstoreViewModel()
    {
        m_bookSku = winrt::make<Bookstore::implementation::BookSku>(L"Atticus");
    }

    Bookstore::BookSku BookstoreViewModel::BookSku()
    {
        return m_bookSku;
    }
}

注意

m_bookSku 的類型是投影類型 (winrt::Bookstore::BookSku),且您搭配 winrt::make 使用的範本參數是實作類型 (winrt::Bookstore::implementation::BookSku)。The type of m_bookSku is the projected type (winrt::Bookstore::BookSku), and the template parameter that you use with winrt::make is the implementation type (winrt::Bookstore::implementation::BookSku). 即便如此,make 傳回投影類型的執行個體。Even so, make returns an instance of the projected type.

現在,專案會再次建置。The project will build again now.

將類型的屬性 BookstoreViewModel 新增至 MainPageAdd a property of type BookstoreViewModel to MainPage

開放 MainPage.idl,其宣告代表我們主要 UI 頁面的執行階段類別。Open MainPage.idl, which declares the runtime class that represents our main UI page.

  • 加入 import 指示詞以匯入 BookstoreViewModel.idlAdd an import directive to import BookstoreViewModel.idl.
  • 加入名為 MainViewModel 且類型為 BookstoreViewModel 的唯讀屬性。Add a read-only property named MainViewModel, of type BookstoreViewModel.
  • 移除 MyProperty 屬性。Remove the MyProperty property.
// MainPage.idl
import "BookstoreViewModel.idl";

namespace Bookstore
{
    runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
    {
        MainPage();
        BookstoreViewModel MainViewModel{ get; };
    }
}

儲存檔案。Save the file. 此專案尚未完全建置成功,但在此時建置是實用的做法,因為專案會重新產生原始程式碼檔案,而檔案中會實作 MainPage 執行階段類別 (\Bookstore\Bookstore\Generated Files\sources\MainPage.hMainPage.cpp)。The project won't entirely succeed in building yet, but building now is a useful thing to do because it regenerates the source code files in which the MainPage runtime class is implemented (\Bookstore\Bookstore\Generated Files\sources\MainPage.h and MainPage.cpp). 因此繼續執行並立即建置。So go ahead and build now. 您預期在這個階段看見的建置錯誤為 'MainViewModel': 不是 'winrt::Bookstore::implementation::MainPage' 的成員The build error you can expect to see at this stage is 'MainViewModel': is not a member of 'winrt::Bookstore::implementation::MainPage'.

如果您省略包含 BookstoreViewModel.idl (請查看上面的 MainPage.idl 清單),則會看到 <"MainViewModel" 附近的預期錯誤。If you omit the include of BookstoreViewModel.idl (see the listing of MainPage.idl above), then you'll see the error expecting < near "MainViewModel". 另一個訣竅是,確定您將所有類型都留在相同的命名空間中 — 顯示在程式碼中的命名空間。Another tip is to make sure that you leave all types in the same namespace—the namespace that's shown in the code listings.

若要解決我們預期會看見的錯誤,您現在必須從所產生的檔案 (\Bookstore\Bookstore\Generated Files\sources\MainPage.hMainPage.cpp) 複製 MainViewModel 屬性的存取子虛設常式,並貼到 \Bookstore\Bookstore\MainPage.hMainPage.cpp 中。To resolve the error that we expect to see, you'll now need to copy the accessor stubs for the MainViewModel property out of the generated files (\Bookstore\Bookstore\Generated Files\sources\MainPage.h and MainPage.cpp) and into \Bookstore\Bookstore\MainPage.h and MainPage.cpp. 接下來說明這麼做的步驟。The steps to do that are described next.

\Bookstore\Bookstore\MainPage.h 中,執行以下步驟。In \Bookstore\Bookstore\MainPage.h, perform these steps.

  • 包含 BookstoreViewModel.h,其會宣告 BookstoreViewModel 的實作類型 (也就是 winrt::Bookstore::implementation::BookstoreViewModel)。Include BookstoreViewModel.h, which declares the implementation type for BookstoreViewModel (which is winrt::Bookstore::implementation::BookstoreViewModel).
  • 新增私用成員以儲存檢視模型。Add a private member to store the view model. 請注意,按照 BookstoreViewModel (這是 Bookstore::BookstoreViewModel) 的投影類型,實作屬性存取子函式 (以及成員 m_mainViewModel)。Note that the property accessor function (and the member m_mainViewModel) is implemented in terms of the projected type for BookstoreViewModel (which is Bookstore::BookstoreViewModel).
  • 實作類型是在與應用程式相同的專案 (編譯單位) 中,因此我們透過採用 std::nullptr_t 的建構函式多載建構 m_mainViewModelThe implementation type is in the same project (compilation unit) as the application, so we construct m_mainViewModel via the constructor overload that takes std::nullptr_t.
  • 移除 MyProperty 屬性。Remove the MyProperty property.

注意

在下面的 MainPage.hMainPage.cpp 中,程式碼闡述了建構 m_mainViewModel 資料成員的預設方式。In the pair of listings below for MainPage.h and MainPage.cpp, the code illustrates the default way of constructing the m_mainViewModel data member. 在接下來的章節中,我們將介紹使用了統一建構的版本。In the section that follows, we'll show a version that uses uniform construction instead.

// MainPage.h
...
#include "BookstoreViewModel.h"
...
namespace winrt::Bookstore::implementation
{
    struct MainPage : MainPageT<MainPage>
    {
        MainPage();

        Bookstore::BookstoreViewModel MainViewModel();

        void ClickHandler(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::RoutedEventArgs const&);

    private:
        Bookstore::BookstoreViewModel m_mainViewModel{ nullptr };
    };
}
...

\Bookstore\Bookstore\MainPage.cpp 中,如下列清單所示,進行下列變更。In \Bookstore\Bookstore\MainPage.cpp, as shown in the listing below, make the following changes.

  • 呼叫 winrt::make (搭配 BookstoreViewModel 實作類型) 將一個 BookstoreViewModel 投影類型的新執行個體指派給 m_mainViewModelCall winrt::make (with the BookstoreViewModel implementation type) to assign a new instance of the projected BookstoreViewModel type to m_mainViewModel. 如先前所見,BookstoreViewModel 建構函式會建立新的 BookSku 物件做為私人資料成員,一開始就將其標題設定為 L"Atticus"As we saw above, the BookstoreViewModel constructor creates a new BookSku object as a private data member, setting its title initially to L"Atticus".
  • 在按鈕的事件處理常式 (ClickHandler) 中,將書籍的標題更新為其已發佈的標題。In the button's event handler (ClickHandler), update the book's title to its published title.
  • 實作 MainViewModel 屬性的存取子。Implement the accessor for the MainViewModel property.
  • 移除 MyProperty 屬性。Remove the MyProperty property.
// MainPage.cpp
#include "pch.h"
#include "MainPage.h"
#include "MainPage.g.cpp"

using namespace winrt;
using namespace Windows::UI::Xaml;

namespace winrt::Bookstore::implementation
{
    MainPage::MainPage()
    {
        m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();
        InitializeComponent();
    }

    void MainPage::ClickHandler(Windows::Foundation::IInspectable const& /* sender */, Windows::UI::Xaml::RoutedEventArgs const& /* args */)
    {
        MainViewModel().BookSku().Title(L"To Kill a Mockingbird");
    }

    Bookstore::BookstoreViewModel MainPage::MainViewModel()
    {
        return m_mainViewModel;
    }
}

統一建構Uniform construction

為了使用統一建構來代替 winrt::make,請在 MainPage.h 中用一個步驟宣告並初始化 m_mainViewModel,如下所示。To use uniform construction instead of winrt::make, in MainPage.h declare and initialize m_mainViewModel in just one step, as shown below.

// MainPage.h
...
#include "BookstoreViewModel.h"
...
struct MainPage : MainPageT<MainPage>
{
    ...
private:
    Bookstore::BookstoreViewModel m_mainViewModel;
};
...

然後,在 MainPage.cppMainPage 建構函式中,不需要程式碼 m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();And then, in the MainPage constructor in MainPage.cpp, there's no need for the code m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();.

如需統一建構的詳細資訊和程式碼範例,請參閱加入統一建構和直接實作存取For more info about uniform construction, and code examples, see Opt in to uniform construction, and direct implementation access.

將按鈕繫結至 Title 屬性Bind the button to the Title property

開啟 MainPage.xaml,其中包含我們主要 UI 頁面的 XAML 標記。Open MainPage.xaml, which contains the XAML markup for our main UI page. 如以下清單所示,從按鈕移除名稱,然後從一個常值變更其 Content 屬性為繫結運算式。As shown in the listing below, remove the name from the button, and change its Content property value from a literal to a binding expression. 注意繫結運算式上的 Mode=OneWay (單向從檢視模型到 UI)。Note the Mode=OneWay property on the binding expression (one-way from the view model to the UI). 沒有該屬性,UI 不會回應變更事件的屬性。Without that property, the UI will not respond to property changed events.

<Button Click="ClickHandler" Content="{x:Bind MainViewModel.BookSku.Title, Mode=OneWay}"/>

現在建置並執行專案。Now build and run the project. 按一下按鈕執行 [按一下] 事件處理常式。Click the button to execute the Click event handler. 該處理常式呼叫本書標題更動子函式;該更動子引發一個事件,讓 UI 知道 Title 屬性已變更;且按鈕重新查詢該屬性的值,更新其自身的 Content 值。That handler calls the book's title mutator function; that mutator raises an event to let the UI know that the Title property has changed; and the button re-queries that property's value to update its own Content value.

使用 {Binding} 標記延伸搭配 C++/WinRTUsing the {Binding} markup extension with C++/WinRT

對於目前發行的 C++/WinRT 版本,為了能夠使用 {Binding} 標記延伸,您必須實作 ICustomPropertyProviderICustomProperty介面。For the currently released version of C++/WinRT, in order to be able to use the {Binding} markup extension you'll need to implement the ICustomPropertyProvider and ICustomProperty interfaces.

元素繫結Element-to-element binding

您可以將一個 XAML 元素的屬性繫結至另一個 XAML 元素的屬性。You can bind the property of one XAML element to the property of another XAML element. 以下是其在標記中的作法範例。Here's an example of how that looks in markup.

<TextBox x:Name="myTextBox" />
<TextBlock Text="{x:Bind myTextBox.Text, Mode=OneWay}" />

您必須將具名的 XAML 實體 myTextBox 宣告為 Midl 檔 (.idl) 中的唯讀屬性。You'll need to declare the named XAML entity myTextBox as a read-only property in your Midl file (.idl).

// MainPage.idl
runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
{
    MainPage();
    Windows.UI.Xaml.Controls.TextBox myTextBox{ get; };
}

以下是這項必要性的原因。Here's the reason for this necessity. 所有 XAML 編譯器需要驗證的類型 (包括用於 {x:Bind} 的類型),都會從 Windows 中繼資料 (WinMD) 進行讀取。All types that the XAML compiler needs to validate (including those used in {x:Bind}) are read from Windows Metadata (WinMD). 您只需要將唯讀屬性新增至 Midl 檔即可。All you need to do is to add the read-only property to your Midl file. 無須進行實作,因為自動產生的 XAML 後方程式碼會為您提供實作。Don't implement it, because the autogenerated XAML code-behind provides the implementation for you.

取用 XAML 標記中的物件Consuming objects from XAML markup

使用 XAML {x:Bind} 標記延伸 取用的所有實體都必須公開於 IDL 中。All entities consumed by using the XAML {x:Bind} markup extension must be exposed publicly in IDL. 此外,如果 XAML 標記包含另一個也在標記中的元素參考,則該標記的 getter 必須存在於 IDL 中。Furthermore, if XAML markup contains a reference to another element that's also in markup, then the getter for that markup must be present in IDL.

<Page x:Name="MyPage">
    <StackPanel>
        <CheckBox x:Name="UseCustomColorCheckBox" Content="Use custom color"
             Click="UseCustomColorCheckBox_Click" />
        <Button x:Name="ChangeColorButton" Content="Change color"
            Click="{x:Bind ChangeColorButton_OnClick}"
            IsEnabled="{x:Bind UseCustomColorCheckBox.IsChecked.Value, Mode=OneWay}"/>
    </StackPanel>
</Page>

ChangeColorButton 元素會透過繫結參考 UseCustomColorCheckBox 元素。The ChangeColorButton element refers to the UseCustomColorCheckBox element via binding. 因此,此頁面的 IDL 必須宣告名為 UseCustomColorCheckBox 的唯讀屬性,以便可供繫結存取。So the IDL for this page must declare a read-only property named UseCustomColorCheckBox in order for it to be accessible to binding.

UseCustomColorCheckBox 的 Click 事件處理常式委派會使用傳統 XAML 委派語法,因此不需要 IDL 中的項目;它只需在您的實作類別中是公用的。The click event handler delegate for UseCustomColorCheckBox uses classic XAML delegate syntax, so that doesn't need an entry in the IDL; it just needs to be public in your implementation class. 另一方面,ChangeColorButton 也有 {x:Bind} Click 事件處理常式,其也必須放入 IDL 中。On the other hand, ChangeColorButton also has an {x:Bind} click event handler, which must also go into the IDL.

runtimeclass MyPage : Windows.UI.Xaml.Controls.Page
{
    MyPage();

    // These members are consumed by binding.
    void ChangeColorButton_OnClick();
    Windows.UI.Xaml.Controls.CheckBox UseCustomColorCheckBox{ get; };
}

您不需要提供 UseCustomColorCheckBox 屬性的實作。You don't need to provide an implementation for the UseCustomColorCheckBox property. XAML 程式碼產生器會為您執行此動作。The XAML code generator does that for you.

繫結至布林值Binding to Boolean

您可以在診斷模式下執行此動作。You might do this in a diagnostic mode.

這會在 C++/CX 中顯示 truefalse,但在 C++/WinRT 中顯示 Windows.Foundation.IReference`1This shows true or false in C++/CX, but shows Windows.Foundation.IReference`1 in C++/WinRT.

繫結至布林值時使用 x:BindUse x:Bind when binding to a Boolean.

<TextBlock Text="{x:Bind CanPair}"/>

重要 APIImportant APIs