深入了解資料繫結Data binding in depth

重要 APIImportant APIs

注意

這個主題將提供資料繫結功能的詳細說明。This topic describes data binding features in detail. 如需簡短且實用的簡介,請參閱資料繫結概觀For a short, practical introduction, see Data binding overview.

此主題的內容與通用 Windows 平台 (UWP) 應用程式中的資料繫結有關。This topic is about data binding in Universal Windows Platform (UWP) applications. 此處所討論的 API 位於 Windows.UI.Xaml.Data 命名空間The APIs discussed here reside in the Windows.UI.Xaml.Data namespace.

資料繫結可讓您的 App UI 顯示資料,以及選擇性地與該資料保持同步。Data binding is a way for your app's UI to display data, and optionally to stay in sync with that data. 資料繫結可讓您將資料與 UI 分開考量,為應用程式建構更簡單的概念模型,以及更好的可讀性、測試性和維護性。Data binding allows you to separate the concern of data from the concern of UI, and that results in a simpler conceptual model as well as better readability, testability, and maintainability of your app.

資料繫結可讓您在 UI 最初顯示時,單純地顯示資料來源的值,而不是要回應這些值的變更。You can use data binding to simply display values from a data source when the UI is first shown, but not to respond to changes in those values. 這是一種繫結模式,稱為「一次性」 ,而且適用於在執行階段期間不會變更的值。This is a mode of binding called one-time, and it works well for a value that doesn't change during run-time. 或者,您可以選擇「觀察」這些值,並於值變更時更新 UI。Alternatively, you can choose to "observe" the values and to update the UI when they change. 此模式稱為「單向」 ,適用於唯讀資料。This mode is called one-way, and it works well for read-only data. 最後,您可以選擇同時觀察和更新,將使用者對 UI 中的值所做的變更,自動推回到資料來源。Ultimately, you can choose to both observe and update, so that changes that the user makes to values in the UI are automatically pushed back into the data source. 此模式稱為「雙向」 ,適用於讀寫資料。This mode is called two-way, and it works well for read-write data. 以下是一些範例。Here are some examples.

  • 您可以使用一次性模式將 Image (英文) 繫結到目前使用者的相片。You could use the one-time mode to bind an Image to the current user's photo.
  • 您可以使用單向模式將 ListView (英文) 繫結到依報紙區段分組的即時新聞文章集合。You could use the one-way mode to bind a ListView to a collection of real-time news articles grouped by newspaper section.
  • 您可以使用雙向模式將 TextBox (英文) 繫結到表單中的客戶名稱。You could use the two-way mode to bind a TextBox to a customer's name in a form.

與模式無關,繫結有兩種,通常都在 UI 標記中宣告。Independent of mode, there are two kinds of binding, and they're both typically declared in UI markup. 您可以選擇使用 {x:Bind} 標記延伸{Binding} 標記延伸You can choose to use either the {x:Bind} markup extension or the {Binding} markup extension. 您甚至可以在相同的 app 中將兩者混用 (甚至在相同的 UI 元素上)。And you can even use a mixture of the two in the same app—even on the same UI element. {x:Bind} 是 Windows 10 新增的標記,效能更好。{x:Bind} is new for Windows 10 and it has better performance. 本主題所述的所有詳細資料適用於這兩種繫結類型,除非明確指出不是如此。All the details described in this topic apply to both kinds of binding unless we explicitly say otherwise.

示範 {x:Bind} 的範例應用程式Sample apps that demonstrate {x:Bind}

示範 {Binding} 的範例應用程式Sample apps that demonstrate {Binding}

每個繫結包含這些項目Every binding involves these pieces

  • 繫結來源A binding source. 這是繫結的資料來源,可以是任何類別的執行個體,且其成員有您想在 UI 中顯示的值。This is the source of the data for the binding, and it can be an instance of any class that has members whose values you want to display in your UI.
  • 繫結目標A binding target. 這是 UI 中用來顯示資料的 FrameworkElementDependencyPropertyThis is a DependencyProperty of the FrameworkElement in your UI that displays the data.
  • 繫結物件A binding object. 此項目將資料值從來源傳輸到目標,也可以從目標傳回到源。This is the piece that transfers data values from the source to the target, and optionally from the target back to the source. 繫結物件是在 XAML 載入時從 {x:Bind}{Binding} 標記延伸建立。The binding object is created at XAML load time from your {x:Bind} or {Binding} markup extension.

在下列各節,我們將詳細說明繫結來源、繫結目標和繫結物件。In the following sections, we'll take a closer look at the binding source, the binding target, and the binding object. 我們以一個範例來串連各節,此範例將一個按鈕的內容繫結到 HostViewModel 類別的 NextButtonText 字串屬性。And we'll link the sections together with the example of binding a button's content to a string property named NextButtonText, which belongs to a class named HostViewModel.

繫結來源Binding source

以下是一個非常基本的類別實作,可做為繫結來源。Here's a very rudimentary implementation of a class that we could use as a binding source.

如果您使用 C++/WinRT,請將新的 Midl 檔案 (.idl) 項目加入專案中,如下列 C++/WinRT 程式碼範例所示。If you're using C++/WinRT, then add new Midl File (.idl) items to the project, named as shown in the C++/WinRT code example listing below. 以清單中顯示的 MIDL 3.0 程式碼取代那些新檔案的內容、建置專案以產生 HostViewModel.h.cpp,然後將程式碼新增至產生的檔案,以符合清單。Replace the contents of those new files with the MIDL 3.0 code shown in the listing, build the project to generate HostViewModel.h and .cpp, and then add code to the generated files to match the listing. 如需有關那些產生的檔案以及如何將其複製到專案中的詳細資訊,請參閱 XAML 控制項;繫結至一個 C++/WinRT 屬性For more info about those generated files and how to copy them into your project, see XAML controls; bind to a C++/WinRT property.

public class HostViewModel
{
    public HostViewModel()
    {
        this.NextButtonText = "Next";
    }

    public string NextButtonText { get; set; }
}
// HostViewModel.idl
namespace DataBindingInDepth
{
    runtimeclass HostViewModel
    {
        HostViewModel();
        String NextButtonText;
    }
}

// HostViewModel.h
// Implement the constructor like this, and add this field:
...
HostViewModel() : m_nextButtonText{ L"Next" } {}
...
private:
    std::wstring m_nextButtonText;
...

// HostViewModel.cpp
// Implement like this:
...
hstring HostViewModel::NextButtonText()
{
    return hstring{ m_nextButtonText };
}

void HostViewModel::NextButtonText(hstring const& value)
{
    m_nextButtonText = value;
}
...

HostViewModel 的實作及其屬性 NextButtonText 僅適用於一次性繫結。That implementation of HostViewModel, and its property NextButtonText, are only appropriate for one-time binding. 單向與雙向繫結很常見,在這些繫結類型中,UI 會隨著繫結來源的資料值變更而自動更新。But one-way and two-way bindings are extremely common, and in those kinds of binding the UI automatically updates in response to changes in the data values of the binding source. 為了讓這些繫結類型正常運作,您需要讓繫結物件「可觀察」您的繫結來源。In order for those kinds of binding to work correctly, you need to make your binding source "observable" to the binding object. 因此,在範例中,如果我們要單向或雙向繫結到 NextButtonText 屬性,則該屬性的值在執行階段發生的任何變更,都必須讓繫結物件可觀察。So in our example, if we want to one-way or two-way bind to the NextButtonText property, then any changes that happen at run-time to the value of that property need to be made observable to the binding object.

作法之一是從 DependencyObject 衍生代表繫結來源的類別,並透過 DependencyProperty 公開資料值。One way of doing that is to derive the class that represents your binding source from DependencyObject, and expose a data value through a DependencyProperty. 這樣 FrameworkElement 就變成可觀察。That's how a FrameworkElement becomes observable. FrameworkElements 是很好用的現成繫結來源。FrameworkElements are good binding sources right out of the box.

將類別變成可觀察還有更簡便的作法,也是已有基底類別的類別的必要作法,就是實作 System.ComponentModel.INotifyPropertyChangedA more lightweight way of making a class observable—and a necessary one for classes that already have a base class—is to implement System.ComponentModel.INotifyPropertyChanged. 這只需要實作一個名為 PropertyChanged 的事件。This really just involves implementing a single event named PropertyChanged. 以下是使用 HostViewModel 的範例。An example using HostViewModel is below.

...
using System.ComponentModel;
using System.Runtime.CompilerServices;
...
public class HostViewModel : INotifyPropertyChanged
{
    private string nextButtonText;

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public HostViewModel()
    {
        this.NextButtonText = "Next";
    }

    public string NextButtonText
    {
        get { return this.nextButtonText; }
        set
        {
            this.nextButtonText = value;
            this.OnPropertyChanged();
        }
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
// HostViewModel.idl
namespace DataBindingInDepth
{
    runtimeclass HostViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
    {
        HostViewModel();
        String NextButtonText;
    }
}

// HostViewModel.h
// Add this field:
...
    winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
    void PropertyChanged(winrt::event_token const& token) noexcept;

private:
    winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
...

// HostViewModel.cpp
// Implement like this:
...
void HostViewModel::NextButtonText(hstring const& value)
{
    if (m_nextButtonText != value)
    {
        m_nextButtonText = value;
        m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"NextButtonText" });
    }
}

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

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

NextButtonText 屬性現在已變成可觀察的。Now the NextButtonText property is observable. 當您撰寫該屬性的單向或雙向繫結時 (稍後說明作法本),產生的繫結物件會訂閱 PropertyChanged 事件。When you author a one-way or a two-way binding to that property (we'll show how later), the resulting binding object subscribes to the PropertyChanged event. 該事件引發時,繫結物件的處理常式會收到一個引數,其中包含已變更的屬性的名稱。When that event is raised, the binding object's handler receives an argument containing the name of the property that has changed. 就是這樣,繫結物件才知道要再次讀取哪個屬性的值。That's how the binding object knows which property's value to go and read again.

因此,您不需要實作上述模式許多次,如果您使用的是 C#,則直接衍生自 QuizGame (英文) 範例 (在 "Common" 資料夾) 中的 BindableBase 基底類別即可。So that you don't have to implement the pattern shown above multiple times, if you're using C# then you can just derive from the BindableBase base class that you'll find in the QuizGame sample (in the "Common" folder). 以下是作法的範例。Here's an example of how that looks.

public class HostViewModel : BindableBase
{
    private string nextButtonText;

    public HostViewModel()
    {
        this.NextButtonText = "Next";
    }

    public string NextButtonText
    {
        get { return this.nextButtonText; }
        set { this.SetProperty(ref this.nextButtonText, value); }
    }
}
// Your BindableBase base class should itself derive from Windows::UI::Xaml::DependencyObject. Then, in HostViewModel.idl, derive from BindableBase instead of implementing INotifyPropertyChanged.

注意

針對 C++/WinRT,從基底類別衍生的任何執行階段類別 (您在您的應用程式中宣告),都稱為「可組合」 類別。For C++/WinRT, any runtime class that you declare in your application that derives 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.

以引數 String.Emptynull 引發 PropertyChanged 事件時,表示應該重新讀取物件上的所有非索引子屬性。Raising the PropertyChanged event with an argument of String.Empty or null indicates that all non-indexer properties on the object should be re-read. 您可以針對特定索引子使用引數 "Item[indexer]" (其中 indexer 是索引值),或針對所有索引子使用值 "Item[]",以引發事件來指出物件上的索引子屬性已變更。You can raise the event to indicate that indexer properties on the object have changed by using an argument of "Item[indexer]" for specific indexers (where indexer is the index value), or a value of "Item[]" for all indexers.

繫結來源可以視為單一物件 (屬性包含資料) 或物件集合。A binding source can be treated either as a single object whose properties contain data, or as a collection of objects. 在 C# 與 Visual Basic 程式碼中,您可以一次性繫結到實作 List(Of T) (部分機器翻譯) 的物件,以顯示不會在執行階段變更的集合。In C# and Visual Basic code, you can one-time bind to an object that implements List(Of T) to display a collection that doesn't change at run-time. 對於可觀察的集合 (觀察集合中新增和移除項目),則改為單向繫結到 ObservableCollection(Of T) For an observable collection (observing when items are added to and removed from the collection), one-way bind to ObservableCollection(Of T) instead. 在 C++/CX 程式碼中,針對可觀察和不可觀察的集合,您都可以繫結到 Vector<T> (部分機器翻譯),且 C++/WinRT 具有自己的類型。In C++/CX code, you can bind to Vector<T> for both observable and non-observable collections, and C++/WinRT has its own types. 如果要繫結到您自己的集合類別,請使用下表中的指導方針。To bind to your own collection classes, use the guidance in the following table.

案例Scenario C# 及 VB (CLR)C# and VB (CLR) C++/WinRTC++/WinRT C++/CXC++/CX
繫結到物件。Bind to an object. 可為任何物件。Can be any object. 可為任何物件。Can be any object. 物件必須具有 BindableAttribute 或實作 ICustomPropertyProviderObject must have BindableAttribute or implement ICustomPropertyProvider.
取得繫結物件的屬性變更通知。Get property change notifications from a bound object. 物件必須實作 INotifyPropertyChanged (部分機器翻譯)。Object must implement INotifyPropertyChanged. 物件必須實作 INotifyPropertyChanged (英文)。Object must implement INotifyPropertyChanged. 物件必須實作 INotifyPropertyChanged (英文)。Object must implement INotifyPropertyChanged.
繫結到集合。Bind to a collection. List(Of T) (部分機器翻譯)List(Of T) IInspectableIVector,或者 IBindableObservableVectorIVector of IInspectable, or IBindableObservableVector. 請參閱 XAML 項目控制項;繫結至 C++/WinRT 集合使用 C++/WinRT 的集合See XAML items controls; bind to a C++/WinRT collection and Collections with C++/WinRT. Vector<T> (部分機器翻譯)Vector<T>
取得繫結集合的集合變更通知。Get collection change notifications from a bound collection. ObservableCollection(Of T) (部分機器翻譯)ObservableCollection(Of T) IInspectableIObservableVectorIObservableVector of IInspectable. 例如,winrt::single_threaded_observable_vector<T> (部分機器翻譯)。For example, winrt::single_threaded_observable_vector<T>. IObservableVector<T> (英文)。IObservableVector<T>. Vector<T> (部分機器翻譯) 會實作這個介面。Vector<T> implements this interface.
實作支援繫結的集合。Implement a collection that supports binding. 擴充 List(Of T) 或實作 IListIList(Of Object)、IEnumerableIEnumerable(Of Object)。Extend List(Of T) or implement IList, IList(Of Object), IEnumerable, or IEnumerable(Of Object). 不支援繫結到泛型 IList(Of T)IEnumerable(Of T)Binding to generic IList(Of T) and IEnumerable(Of T) is not supported. 實作 IInspectableIVectorImplement IVector of IInspectable. 請參閱 XAML 項目控制項;繫結至 C++/WinRT 集合使用 C++/WinRT 的集合See XAML items controls; bind to a C++/WinRT collection and Collections with C++/WinRT. 實作 IBindableVectorIBindableIterableIVector<Object^>、IIterable<Object^>、IVector<IInspectable*> 或 IIterable<IInspectable*>。Implement IBindableVector, IBindableIterable, IVector<Object^>, IIterable<Object^>, IVector<IInspectable*>, or IIterable<IInspectable*>. 不支援繫結到泛型 IVector<T>IIterable<T>Binding to generic IVector<T> and IIterable<T> is not supported.
實作可支援集合變更通知的集合。Implement a collection that supports collection change notifications. 擴充 ObservableCollection(Of T) 或實作 (非泛型) IListINotifyCollectionChangedExtend ObservableCollection(Of T) or implement (non-generic) IList and INotifyCollectionChanged. 實作 IInspectableIObservableVector,或 IBindableObservableVectorImplement IObservableVector of IInspectable, or IBindableObservableVector. 實作 IBindableVectorIBindableObservableVectorImplement IBindableVector and IBindableObservableVector.
實作支援增量載入的集合。Implement a collection that supports incremental loading. 擴充 ObservableCollection(Of T) 或實作 (非泛型) IListINotifyCollectionChangedExtend ObservableCollection(Of T) or implement (non-generic) IList and INotifyCollectionChanged. 此外,也實作 ISupportIncrementalLoadingAdditionally, implement ISupportIncrementalLoading. 實作 IInspectableIObservableVector,或 IBindableObservableVectorImplement IObservableVector of IInspectable, or IBindableObservableVector. 此外,也實作 ISupportIncrementalLoading (英文)Additionally, implement ISupportIncrementalLoading 實作 IBindableVectorIBindableObservableVectorISupportIncrementalLoadingImplement IBindableVector, IBindableObservableVector, and ISupportIncrementalLoading.

您可以使用增量載入將清單控制項繫結到任意大的資料來源,而仍然保有高效能。You can bind list controls to arbitrarily large data sources, and still achieve high performance, by using incremental loading. 例如,您可以將清單控制項繫結到 Bing 影像查詢結果,而不需一次載入所有結果。For example, you can bind list controls to Bing image query results without having to load all the results at once. 改為只立即載入一些結果,再視需要載入額外的結果。Instead, you load only some results immediately, and load additional results as needed. 若要支援增量載入,您必須在支援集合變更通知的資料來源上實作 ISupportIncrementalLoading (英文)。To support incremental loading, you must implement ISupportIncrementalLoading on a data source that supports collection change notifications. 當資料繫結引擎要求更多資料時,您的資料來源必須提出適當的要求、整合結果,然後傳送適當的通知來更新 UI。When the data binding engine requests more data, your data source must make the appropriate requests, integrate the results, and then send the appropriate notifications in order to update the UI.

繫結目標Binding target

在下列兩個範例中,Button.Content 屬性是繫結目標,而其值設定為宣告繫結物件的標記延伸模組。In the two examples below, the Button.Content property is the binding target, and its value is set to a markup extension that declares the binding object. 首先顯示 {x:Bind},接著顯示 {Binding}First {x:Bind} is shown, and then {Binding}. 通常是在標記中宣告繫結 (方便、易讀、可加工)。Declaring bindings in markup is the common case (it's convenient, readable, and toolable). 但如果需要的話,您可以避免使用標記,改為立即 (以程式設計方式) 建立 Binding 類別的執行個體。But you can avoid markup and imperatively (programmatically) create an instance of the Binding class instead if you need to.

<Button Content="{x:Bind ...}" ... />
<Button Content="{Binding ...}" ... />

如果您使用 C++/WinRT 或 Visual C++ 元件延伸模組 (C++/CX),則需要將 BindableAttribute (英文) 屬性新增至您要搭配 {Binding} (部分機器翻譯) 標記延伸使用的任何執行階段類別。If you're using C++/WinRT or Visual C++ component extensions (C++/CX), then you'll need to add the BindableAttribute attribute to any runtime class that you want to use the {Binding} markup extension with.

重要

如果您使用的是 C++/WinRT,則可以使用 BindableAttribute (英文) 屬性 (如果您安裝了 Windows SDK 版本 10.0.17763.0 (Windows 10 版本 1809) 或更新版本)。If you're using C++/WinRT, then the BindableAttribute attribute is available if you've installed the Windows SDK version 10.0.17763.0 (Windows 10, version 1809), or later. 如果沒有該屬性,則需要實作 ICustomPropertyProviderICustomProperty 介面,才能使用 {Binding} (部分機器翻譯) 標記延伸模組。Without that attribute, you'll need to implement the ICustomPropertyProvider and ICustomProperty interfaces in order to be able to use the {Binding} markup extension.

使用 {x:Bind} 宣告的繫結物件Binding object declared using {x:Bind}

在撰寫我們的 {x:Bind} 標記之前,還有一個步驟需要執行。There's one step we need to do before we author our {x:Bind} markup. 我們需要從代表標記頁面的類別中公開繫結來源類別。We need to expose our binding source class from the class that represents our page of markup. 作法是在 MainPage 頁面類別中新增屬性 (在此案例中為 HostViewModel 類型)。We do that by adding a property (of type HostViewModel in this case) to our MainPage page class.

namespace DataBindingInDepth
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.ViewModel = new HostViewModel();
        }
    
        public HostViewModel ViewModel { get; set; }
    }
}
// MainPage.idl
import "HostViewModel.idl";

namespace DataBindingInDepth
{
    runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
    {
        MainPage();
        HostViewModel ViewModel{ get; };
    }
}

// MainPage.h
// Include a header, and add this field:
...
#include "HostViewModel.h"
...
    DataBindingInDepth::HostViewModel ViewModel();

private:
    DataBindingInDepth::HostViewModel m_viewModel{ nullptr };
...

// MainPage.cpp
// Implement like this:
...
MainPage::MainPage()
{
    InitializeComponent();

}

DataBindingInDepth::HostViewModel MainPage::ViewModel()
{
    return m_viewModel;
}
...

完成了,我們現在可以仔細看看宣告繫結物件的標記。That done, we can now take a closer look at the markup that declares the binding object. 下列範例使用稍早已在「繫結目標」一節中使用的 Button.Content 繫結目標,並顯示它已繫結到 HostViewModel.NextButtonText 屬性。The example below uses the same Button.Content binding target we used in the "Binding target" section earlier, and shows it being bound to the HostViewModel.NextButtonText property.

<!-- MainPage.xaml -->
<Page x:Class="DataBindingInDepth.Mainpage" ... >
    <Button Content="{x:Bind Path=ViewModel.NextButtonText, Mode=OneWay}" ... />
</Page>

請注意我們指定給 Path 的值。Notice the value that we specify for Path. 這個值是從頁面本身的角度來解譯,在此案例中,路徑最初會參考我們剛才加入至 MainPage 頁面的屬性 ViewModelThis value is interpreted in the context of the page itself, and in this case the path begins by referencing the ViewModel property that we just added to the MainPage page. 該屬性會傳回 HostViewModel 執行個體,因此我們可以進入該物件來存取 HostViewModel.NextButtonText 屬性。That property returns a HostViewModel instance, and so we can dot into that object to access the HostViewModel.NextButtonText property. 此外,我們會指定 Mode 來覆寫一次性的 {x:Bind} 預設值。And we specify Mode, to override the {x:Bind} default of one-time.

Path 屬性支援多種繫結語法選項,可讓您繫結到巢狀屬性、附加屬性以及整數和字串索引子。The Path property supports a variety of syntax options for binding to nested properties, attached properties, and integer and string indexers. 如需詳細資訊,請參閱 Property-path 語法For more info, see Property-path syntax. 繫結到字串索引子可以提供繫結至動態屬性的效果,卻不需實作 ICustomPropertyProviderBinding to string indexers gives you the effect of binding to dynamic properties without having to implement ICustomPropertyProvider. 如需其他設定,請參閱 {x:Bind} 標記延伸For other settings, see {x:Bind} markup extension.

為了說明 HostViewModel.NextButtonText 屬性確實是可觀察的,請將 Click 事件處理常式新增至按鈕,然後更新 HostViewModel.NextButtonText 的值。To illustrate that the HostViewModel.NextButtonText property is indeed observable, add a Click event handler to the button, and update the value of HostViewModel.NextButtonText. 建置、執行,然後按一下按鈕以查看按鈕內容更新的值。Build, run, and click the button to see the value of the button's Content update.

// MainPage.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    this.ViewModel.NextButtonText = "Updated Next button text";
}
// MainPage.cpp
void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    ViewModel().NextButtonText(L"Updated Next button text");
}

注意

TextBox (英文) 失去焦點時 (不是在使用者每次按下按鍵之後),即會將對於 TextBox.Text (英文) 的變更傳送到雙向繫結來源。Changes to TextBox.Text are sent to a two-way bound source when the TextBox loses focus, and not after every user keystroke.

DataTemplate 與 x:DataTypeDataTemplate and x:DataType

DataTemplate 內 (不論是用來做為項目範本、內容範本或標頭範本),Path 的值不是從頁面的內容來解譯,而是根據樣板化的資料物件來解譯。Inside a DataTemplate (whether used as an item template, a content template, or a header template), the value of Path is not interpreted in the context of the page, but in the context of the data object being templated. 因此在資料範本中使用 {x:Bind} 時,可以在編譯階段驗證其繫結 (並為它們產生有效率的程式碼),而 DataTemplate 必須使用 x:DataType 宣告其資料物件的類型。When using {x:Bind} in a data template, so that its bindings can be validated (and efficient code generated for them) at compile-time, the DataTemplate needs to declare the type of its data object using x:DataType. 對於繫結到 SampleDataGroup 物件集合的項目控制項,以下提供的範例可做為其 ItemTemplateThe example given below could be used as the ItemTemplate of an items control bound to a collection of SampleDataGroup objects.

<DataTemplate x:Key="SimpleItemTemplate" x:DataType="data:SampleDataGroup">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{x:Bind Title}"/>
      <TextBlock Text="{x:Bind Description}"/>
    </StackPanel>
  </DataTemplate>

Path 中的弱式類型物件Weakly-typed objects in your Path

假設有一個名為 SampleDataGroup 的類型,其會實作名為 Title 的字串屬性。Consider for example that you have a type named SampleDataGroup, which implements a string property named Title. 而您有一個屬性 MainPage.SampleDataGroupAsObject,其屬於類型物件,但會自動傳回 SampleDataGroup 的執行個體。And you have a property MainPage.SampleDataGroupAsObject, which is of type object, but which actually returns an instance of SampleDataGroup. 由於在此類型物件中找不到 Title 屬性,因此繫結 <TextBlock Text="{x:Bind SampleDataGroupAsObject.Title}"/> 將產生編譯錯誤。The binding <TextBlock Text="{x:Bind SampleDataGroupAsObject.Title}"/> will result in a compile error because the Title property is not found on the type object. 解決此問題的方式是在您的 Path 語法中新增一個轉型,如下所示:<TextBlock Text="{x:Bind ((data:SampleDataGroup)SampleDataGroupAsObject).Title}"/>The remedy for this is to add a cast to your Path syntax like this: <TextBlock Text="{x:Bind ((data:SampleDataGroup)SampleDataGroupAsObject).Title}"/>. 以下是另一個將 Element 宣告為物件但實際為 TextBlock 的範例:<TextBlock Text="{x:Bind Element.Text}"/>Here's another example where Element is declared as object but is actually a TextBlock: <TextBlock Text="{x:Bind Element.Text}"/>. 而且轉型可以解決此問題:<TextBlock Text="{x:Bind ((TextBlock)Element).Text}"/>And a cast remedies the issue: <TextBlock Text="{x:Bind ((TextBlock)Element).Text}"/>.

如果您的資料會以非同步方式載入If your data loads asynchronously

支援 {x:Bind} 的程式碼是在編譯頁面的部分類別時所產生。Code to support {x:Bind} is generated at compile-time in the partial classes for your pages. 您可以在 obj 資料夾中找到這些檔案,其名稱類似於 (適用於 C#) <view name>.g.csThese files can be found in your obj folder, with names like (for C#) <view name>.g.cs. 產生的程式碼包含頁面的 Loading 事件處理常式,而該處理常式會在產生的類別上呼叫 Initialize 方法,其代表頁面的繫結。The generated code includes a handler for your page's Loading event, and that handler calls the Initialize method on a generated class that represent's your page's bindings. Initialize 接著會呼叫 Update,開始在繫結來源與目標之間移動資料。Initialize in turn calls Update to begin moving data between the binding source and the target. Loading 只會在第一次衡量頁面或使用者控制項的階段之前引發。Loading is raised just before the first measure pass of the page or user control. 如果您的資料是以非同步方式載入,可能就不會在呼叫 Initialize 之前備妥。So if your data is loaded asynchronously it may not be ready by the time Initialize is called. 因此,載入資料之後,您可以呼叫 this.Bindings.Update();,強制將一次性繫結初始化。So, after you've loaded data, you can force one-time bindings to be initialized by calling this.Bindings.Update();. 如果您只需要針對以非同步方式載入的資料使用一次性繫結,則將其初始化的方法會比讓其擁有單向繫結並接聽變更來得經濟實惠。If you only need one-time bindings for asynchronously-loaded data then it's much cheaper to initialize them this way than it is to have one-way bindings and to listen for changes. 如果您的資料不能進行細部變更,而且如果它很可能更新為特定動作的一部分,則您可以讓繫結變成一次性,並隨時呼叫 Update 來強制進行手動更新。If your data does not undergo fine-grained changes, and if it's likely to be updated as part of a specific action, then you can make your bindings one-time, and force a manual update at any time with a call to Update.

注意

{x:Bind} 不適合用於晚期繫結案例,例如瀏覽 JSON 物件或鴨子型別的字典結構。{x:Bind} is not suited to late-bound scenarios, such as navigating the dictionary structure of a JSON object, nor duck typing. 「鴨子型別」是以屬性名稱的詞法相符項目為基礎的弱式形式類型 (「如果其走起來像鴨子、游泳起來像鴨子、叫起來也像鴨子,那其就是鴨子」)。"Duck typing" is a weak form of typing based on lexical matches on property names (a in, "if it walks, swims, and quacks like a duck, then it's a duck"). 使用鴨子型別,Age 屬性的繫結同樣可滿足 PersonWine 物件 (假設那些類型都有 Age 屬性)。With duck typing, a binding to the Age property would be equally satisfied with a Person or a Wine object (assuming that those types each had an Age property). 在這些情況下,請使用 {Binding} 標記延伸模組。For these scenarios, use the {Binding} markup extension.

使用 {Binding} 宣告的繫結物件Binding object declared using {Binding}

如果您使用 C++/WinRT 或 Visual C++ 元件延伸模組 (C++/CX),則需要將 BindableAttribute 屬性新增至您希望繫結至之任何執行階段類別,以使用 {Binding} 標記延伸。If you're using C++/WinRT or Visual C++ component extensions (C++/CX) then, to use the {Binding} markup extension, you'll need to add the BindableAttribute attribute to any runtime class that you want to bind to. 若要使用 {x:Bind},您不需要該屬性。To use {x:Bind}, you don't need that attribute.

// HostViewModel.idl
// Add this attribute:
[Windows.UI.Xaml.Data.Bindable]
runtimeclass HostViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
...

重要

如果您使用的是 C++/WinRT,則可以使用 BindableAttribute 屬性,前提是您安裝了 Windows SDK 版本 10.0.17763.0 (Windows 10 版本 1809) 或更新版本。If you're using C++/WinRT, then the BindableAttribute attribute is available if you've installed the Windows SDK version 10.0.17763.0 (Windows 10, version 1809), or later. 如果沒有該屬性,則需要實作 ICustomPropertyProviderICustomProperty 介面,才能使用 {Binding} (部分機器翻譯) 標記延伸模組。Without that attribute, you'll need to implement the ICustomPropertyProvider and ICustomProperty interfaces in order to be able to use the {Binding} markup extension.

{Binding} 預設會假設您繫結到標記頁面的 DataContext{Binding} assumes, by default, that you're binding to the DataContext of your markup page. 我們會將頁面的 DataContext 設定為繫結來源類別的執行個體 (在此案例中為 HostViewModel 類型)。So we'll set the DataContext of our page to be an instance of our binding source class (of type HostViewModel in this case). 下列範例顯示宣告繫結物件的標記。The example below shows the markup that declares the binding object. 我們使用稍早已在「繫結目標」一節中使用的 Button.Content 繫結目標,並繫結到 HostViewModel.NextButtonText 屬性。We use the same Button.Content binding target we used in the "Binding target" section earlier, and we bind to the HostViewModel.NextButtonText property.

<Page xmlns:viewmodel="using:DataBindingInDepth" ... >
    <Page.DataContext>
        <viewmodel:HostViewModel x:Name="viewModelInDataContext"/>
    </Page.DataContext>
    ...
    <Button Content="{Binding Path=NextButtonText}" ... />
</Page>
// MainPage.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    this.viewModelInDataContext.NextButtonText = "Updated Next button text";
}
// MainPage.cpp
void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    viewModelInDataContext().NextButtonText(L"Updated Next button text");
}

請注意我們指定給 Path 的值。Notice the value that we specify for Path. 這個值是根據頁面的 DataContext 來解譯,在這個範例中,這設定為 HostViewModel 的執行個體。This value is interpreted in the context of the page's DataContext, which in this example is set to an instance of HostViewModel. 路徑參考 HostViewModel.NextButtonText 屬性。The path references the HostViewModel.NextButtonText property. 我們可以省略 Mode,因為此處採用 {Binding} 預設的單向。We can omit Mode, because the {Binding} default of one-way works here.

UI 元素的 DataContext 的預設值繼承自父代。The default value of DataContext for a UI element is the inherited value of its parent. 當然,您可以明確設定 DataContext 來覆寫該預設值,依預設再由子系繼承。You can of course override that default by setting DataContext explicitly, which is in turn inherited by children by default. 當您想讓多個繫結都使用相同的來源時,在元素上設定 DataContext 是很有用的作法。Setting DataContext explicitly on an element is useful when you want to have multiple bindings that use the same source.

繫結物件有 Source 屬性,預設為宣告繫結的 UI 元素的 DataContextA binding object has a Source property, which defaults to the DataContext of the UI element on which the binding is declared. 您可以在繫結上明確設定 SourceRelativeSourceElementName,以覆寫這個預設值 (如需詳細資訊,請參閱 {Binding})。You can override this default by setting Source, RelativeSource, or ElementName explicitly on the binding (see {Binding} for details).

DataTemplate (英文) 內,DataContext (英文) 設定為樣板化的資料物件。Inside a DataTemplate, the DataContext is automatically set to the data object being templated. 如果項目控制項繫結到任何類型的集合,且這些類型有 TitleDescription 字串屬性,以下提供的範例可做為其 ItemTemplateThe example given below could be used as the ItemTemplate of an items control bound to a collection of any type that has string properties named Title and Description.

<DataTemplate x:Key="SimpleItemTemplate">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{Binding Title}"/>
      <TextBlock Text="{Binding Description"/>
    </StackPanel>
  </DataTemplate>

注意

根據預設,當 TextBox (英文) 失去焦點時,TextBox.Text (英文) 的變更會傳送到雙向繫結來源。By default, changes to TextBox.Text are sent to a two-way bound source when the TextBox loses focus. 若要在使用者每次按下按鍵輸入傳送變更,請在標記中的繫結上將 UpdateSourceTrigger 設定為 PropertyChangedTo cause changes to be sent after every user keystroke, set UpdateSourceTrigger to PropertyChanged on the binding in markup. 您可以也將 UpdateSourceTrigger 設定為 Explicit,以完全掌控何時將變更傳送到來源。You can also completely take control of when changes are sent to the source by setting UpdateSourceTrigger to Explicit. 接著需要處理文字方塊上的事件 (通常是 TextBox.TextChanged)、在目標上呼叫 GetBindingExpression 以取得 BindingExpression 物件,最後呼叫 BindingExpression.UpdateSource 以程式設計方式更新資料來源。You then handle events on the text box (typically TextBox.TextChanged), call GetBindingExpression on the target to get a BindingExpression object, and finally call BindingExpression.UpdateSource to programmatically update the data source.

Path 屬性支援多種繫結語法選項,可讓您繫結到巢狀屬性、附加屬性以及整數和字串索引子。The Path property supports a variety of syntax options for binding to nested properties, attached properties, and integer and string indexers. 如需詳細資訊,請參閱 Property-path 語法For more info, see Property-path syntax. 繫結到字串索引子可以提供繫結至動態屬性的效果,卻不需實作 ICustomPropertyProviderBinding to string indexers gives you the effect of binding to dynamic properties without having to implement ICustomPropertyProvider. ElementName 屬性在元素對元素繫結上很有用。The ElementName property is useful for element-to-element binding. RelativeSource 屬性有多種用途,其中之一是以更強大的方式替代 ControlTemplate 內的範本繫結。The RelativeSource property has several uses, one of which is as a more powerful alternative to template binding inside a ControlTemplate. 如需其他設定,請參閱 {Binding} 標記延伸Binding 類別。For other settings, see {Binding} markup extension and the Binding class.

如果來源和目標不是相同類型,該怎麼辦?What if the source and the target are not the same type?

如果您想要根據佈林值屬性的值控制 UI 元素的可見度、想要以數值的範圍或趨勢的函數呈現 UI 元素的色彩,或想要在應該為字串的 UI 元素屬性中顯示日期和/或時間值,則需要將值的類型轉換成另一種類型。If you want to control the visibility of a UI element based on the value of a boolean property, or if you want to render a UI element with a color that's a function of a numeric value's range or trend, or if you want to display a date and/or time value in a UI element property that expects a string, then you'll need to convert values from one type to another. 在某些情況下,正確的解決方案是從繫結來源類別公開正確類型的另一個屬性,但將轉換邏輯封裝在那裡並維持為可測試。There will be cases where the right solution is to expose another property of the right type from your binding source class, and keep the conversion logic encapsulated and testable there. 但是,當您有大量的或組合龐大的來源和目標屬性時,這就顯的缺乏彈性和擴充性。But that isn't flexible nor scalable when you have large numbers, or large combinations, of source and target properties. 在那樣的情況下,您有幾個選項:In that case you have a couple of options:

  • 如果使用 {x:Bind},您可以直接繫結至函式來執行該轉換If using {x:Bind} then you can bind directly to a function to do that conversion
  • 或者您可以指定一個值轉換器,這是為執行轉換所設計的物件Or you can specify a value converter which is an object designed to perform the conversion

值轉換器Value Converters

以下是適用於一次性或單向繫結的值轉換器,可將 DateTime 值轉換成包含月份的字串值。Here's a value converter, suitable for a one-time or a one-way binding, that converts a DateTime value to a string value containing the month. 此類別實作 IValueConverterThe class implements IValueConverter.

public class DateToStringConverter : IValueConverter
{
    // Define the Convert method to convert a DateTime value to 
    // a month string.
    public object Convert(object value, Type targetType, 
        object parameter, string language)
    {
        // value is the data from the source object.
        DateTime thisdate = (DateTime)value;
        int monthnum = thisdate.Month;
        string month;
        switch (monthnum)
        {
            case 1:
                month = "January";
                break;
            case 2:
                month = "February";
                break;
            default:
                month = "Month not found";
                break;
        }
        // Return the value to pass to the target.
        return month;
    }

    // ConvertBack is not implemented for a OneWay binding.
    public object ConvertBack(object value, Type targetType, 
        object parameter, string language)
    {
        throw new NotImplementedException();
    }
}
// See the "Formatting or converting data values for display" section in the "Data binding overview" topic.

以下說明如何在您的繫結物件標記中使用該值轉換器。And here's how you consume that value converter in your binding object markup.

<UserControl.Resources>
  <local:DateToStringConverter x:Key="Converter1"/>
</UserControl.Resources>
...
<TextBlock Grid.Column="0" 
  Text="{x:Bind ViewModel.Month, Converter={StaticResource Converter1}}"/>
<TextBlock Grid.Column="0" 
  Text="{Binding Month, Converter={StaticResource Converter1}}"/>

如果為繫結定義 Converter 參數,那麼繫結引擎就會呼叫 ConvertConvertBack 方法。The binding engine calls the Convert and ConvertBack methods if the Converter parameter is defined for the binding. 從來源傳遞資料時,繫結引擎會呼叫 Convert 並將傳回的資料傳遞到目標。When data is passed from the source, the binding engine calls Convert and passes the returned data to the target. 從目標傳遞資料時 (雙向繫結),繫結引擎會呼叫 ConvertBack,並將傳回的資料傳遞到來源。When data is passed from the target (for a two-way binding), the binding engine calls ConvertBack and passes the returned data to the source.

轉換器也有選用的參數:ConverterLanguage (英文) 可以指定轉換中要使用的語言,而 ConverterParameter (英文) 可允許傳遞轉換邏輯的參數。The converter also has optional parameters: ConverterLanguage, which allows specifying the language to be used in the conversion, and ConverterParameter, which allows passing a parameter for the conversion logic. 如需使用轉換器參數的範例,請參閱 IValueConverterFor an example that uses a converter parameter, see IValueConverter.

注意

如果轉換中出現錯誤,請不要擲回例外狀況。If there is an error in the conversion, do not throw an exception. 而是傳回 DependencyProperty.UnsetValue,以便停止資料傳送。Instead, return DependencyProperty.UnsetValue, which will stop the data transfer.

如果要在繫結來源無法解析時顯示預設值,請在標記中的繫結物件上設定 FallbackValue 屬性。To display a default value to use whenever the binding source cannot be resolved, set the FallbackValue property on the binding object in markup. 這對控制代碼轉換與格式錯誤很有用。This is useful to handle conversion and formatting errors. 繫結到異質類型繫結集合中的所有物件上可能不存在的來源屬性也很有用。It is also useful to bind to source properties that might not exist on all objects in a bound collection of heterogeneous types.

如果您將文字控制項繫結到不是字串的值,資料繫結引擎會將該值轉換為字串。If you bind a text control to a value that is not a string, the data binding engine will convert the value to a string. 如果該值是參照類型,資料繫結引擎會呼叫 ICustomPropertyProvider.GetStringRepresentationIStringable.ToString (若有的話) 來擷取字串值,否則會呼叫 Object.ToStringIf the value is a reference type, the data binding engine will retrieve the string value by calling ICustomPropertyProvider.GetStringRepresentation or IStringable.ToString if available, and will otherwise call Object.ToString. 但請注意,繫結引擎會忽略隱藏基底類別實作的任何 ToString 實作。Note, however, that the binding engine will ignore any ToString implementation that hides the base-class implementation. 子類別實作應該會改而覆寫基底類別 ToString 方法。Subclass implementations should override the base class ToString method instead. 同樣地,在原生語言中,所有 Managed 物件似乎都實作 ICustomPropertyProviderIStringableSimilarly, in native languages, all managed objects appear to implement ICustomPropertyProvider and IStringable. 不過,對 GetStringRepresentationIStringable.ToString 的所有呼叫都會路由傳送到 Object.ToString 或該方法的覆寫,永遠不會路由傳送到隱藏基底類別實作的新 ToString 實作。However, all calls to GetStringRepresentation and IStringable.ToString are routed to Object.ToString or an override of that method, and never to a new ToString implementation that hides the base-class implementation.

注意

從 Windows 10 版本 1607 開始,XAML 架構針對可見度轉換器提供了內建布林值。Starting in Windows 10, version 1607, the XAML framework provides a built in boolean to Visibility converter. 轉換器會將 true 對應至 Visible 列舉值,並將 false 對應至 Collapsed,這樣您就可以將 Visibility 屬性繫結至布林值而不用建立轉換器。The converter maps true to the Visible enumeration value and false to Collapsed so you can bind a Visibility property to a boolean without creating a converter. 若要使用內建轉換器,您 App 的最低目標 SDK 版本必須為 14393 或更新版本。To use the built in converter, your app's minimum target SDK version must be 14393 or later. 當您的 App 是以舊版 Windows 10 為目標時,您就無法使用它。You can't use it when your app targets earlier versions of Windows 10. 如需目標版本的相關詳細資訊,請參閱版本調適型程式碼For more info about target versions, see Version adaptive code.

{x:Bind} 中的函式繫結Function binding in {x:Bind}

{x:Bind} 讓繫結路徑中的最後一個步驟可以是函式。{x:Bind} enables the final step in a binding path to be a function. 這可以用來執行轉換,以及執行和一個以上屬性相依的繫結。This can be used to perform conversions, and to perform bindings that depend on more than one property. 請參閱 x:Bind 中的函式See Functions in x:Bind

元素繫結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}" />

重要

如需使用 C++/WinRT 之元素對元素繫結的必要工作流程,請參閱元素對元素繫結For the necessary workflow for element-to-element binding using C++/WinRT, see Element-to-element binding.

使用 {x:Bind} 的資源字典Resource dictionaries with {x:Bind}

{X:Bind} 標記延伸取決於程式碼產生,因此需要一個程式碼後置檔案,由其中的建構函式呼叫 InitializeComponent (初始化產生的程式碼)。The {x:Bind} markup extension depends on code generation, so it needs a code-behind file containing a constructor that calls InitializeComponent (to initialize the generated code). 重複使用資源字典時需要具現化其類別 (以呼叫 InitializeComponent),而不是參考其檔案名稱。You re-use the resource dictionary by instantiating its type (so that InitializeComponent is called) instead of referencing its filename. 以下是在現有的資源字典中使用 {x:Bind} 的範例。Here's an example of what to do if you have an existing resource dictionary and you want to use {x:Bind} in it.

TemplatesResourceDictionary.xamlTemplatesResourceDictionary.xaml

<ResourceDictionary
    x:Class="ExampleNamespace.TemplatesResourceDictionary"
    .....
    xmlns:examplenamespace="using:ExampleNamespace">
    
    <DataTemplate x:Key="EmployeeTemplate" x:DataType="examplenamespace:IEmployee">
        <Grid>
            <TextBlock Text="{x:Bind Name}"/>
        </Grid>
    </DataTemplate>
</ResourceDictionary>

TemplatesResourceDictionary.xaml.csTemplatesResourceDictionary.xaml.cs

using Windows.UI.Xaml.Data;
 
namespace ExampleNamespace
{
    public partial class TemplatesResourceDictionary
    {
        public TemplatesResourceDictionary()
        {
            InitializeComponent();
        }
    }
}

MainPage.xamlMainPage.xaml

<Page x:Class="ExampleNamespace.MainPage"
    ....
    xmlns:examplenamespace="using:ExampleNamespace">

    <Page.Resources>
        <ResourceDictionary>
            .... 
            <ResourceDictionary.MergedDictionaries>
                <examplenamespace:TemplatesResourceDictionary/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>
</Page>

事件繫結和 ICommandEvent binding and ICommand

{x:Bind} 支援一個稱為「事件繫結」的功能。{x:Bind} supports a feature called event binding. 除了在程式碼後置檔案中使用方法來處理事件,這項功能可讓您使用繫結來指定事件的處理常式。With this feature, you can specify the handler for an event using a binding, which is an additional option on top of handling events with a method on the code-behind file. 假設您的 MainPage 類別有 RootFrame 屬性。Let's say you have a RootFrame property on your MainPage class.

public sealed partial class MainPage : Page
{
    ...
    public Frame RootFrame { get { return Window.Current.Content as Frame; } }
}

同樣地,您可以將按鈕的 Click 事件繫結到 RootFrame 屬性所傳回的 Frame 物件的方法。You can then bind a button's Click event to a method on the Frame object returned by the RootFrame property like this. 請注意,我們也將按鈕的 IsEnabled 屬性繫結到相同 Frame 的另一個成員。Note that we also bind the button's IsEnabled property to another member of the same Frame.

<AppBarButton Icon="Forward" IsCompact="True"
IsEnabled="{x:Bind RootFrame.CanGoForward, Mode=OneWay}"
Click="{x:Bind RootFrame.GoForward}"/>

無法透過這項技巧使用多載方法來處理事件。Overloaded methods cannot be used to handle an event with this technique. 此外,如果處理事件的方法有參數,則必須全部都可以從事件的所有參數的類型分別指派。Also, if the method that handles the event has parameters then they must all be assignable from the types of all of the event's parameters, respectively. 在此案例中,Frame.GoForward 未多載,也沒有參數 (但即使接受兩個 object 參數,仍然有效)。In this case, Frame.GoForward is not overloaded and it has no parameters (but it would still be valid even if it took two object parameters). 儘管 Frame.GoBack (英文) 為多載,我們還是不能透過此技巧使用該方法。Frame.GoBack is overloaded, though, so we can't use that method with this technique.

事件繫結技巧類似於實作與使用命令 (命令是一個屬性,可傳回實作 ICommand 介面的物件)。The event binding technique is similar to implementing and consuming commands (a command is a property that returns an object that implements the ICommand interface). {x:Bind}{Binding} 都能搭配命令一起使用。Both {x:Bind} and {Binding} work with commands. 因此,您不需要實作命令模式許多次,您可以使用 QuizGame 範例 (在 [Common] 資料夾) 中的DelegateCommand 協助程式類別。So that you don't have to implement the command pattern multiple times, you can use the DelegateCommand helper class that you'll find in the QuizGame sample (in the "Common" folder).

繫結到資料夾或檔案集合Binding to a collection of folders or files

您可以使用 Windows.Storage 命名空間中的 API 來擷取資料夾和檔案資料。You can use the APIs in the Windows.Storage namespace to retrieve folder and file data. 不過,GetFilesAsyncGetFoldersAsyncGetItemsAsync 這些各式方法並不會傳回適合繫結到清單控制項的值。However, the various GetFilesAsync, GetFoldersAsync, and GetItemsAsync methods do not return values that are suitable for binding to list controls. 您必須改為繫結到 FileInformationFactory 類別之 GetVirtualizedFilesVectorGetVirtualizedFoldersVectorGetVirtualizedItemsVector 方法的傳回值。Instead, you must bind to the return values of the GetVirtualizedFilesVector, GetVirtualizedFoldersVector, and GetVirtualizedItemsVector methods of the FileInformationFactory class. 下列來自 StorageDataSource 和 GetVirtualizedFilesVector 範例的程式碼範例示範一般的使用模式。The following code example from the StorageDataSource and GetVirtualizedFilesVector sample shows the typical usage pattern. 請記得在您的應用程式套件資訊清單中宣告 picturesLibrary 功能,並確認您的 [圖片庫] 資料夾中有圖片。Remember to declare the picturesLibrary capability in your app package manifest, and confirm that there are pictures in your Pictures library folder.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var library = Windows.Storage.KnownFolders.PicturesLibrary;
    var queryOptions = new Windows.Storage.Search.QueryOptions();
    queryOptions.FolderDepth = Windows.Storage.Search.FolderDepth.Deep;
    queryOptions.IndexerOption = Windows.Storage.Search.IndexerOption.UseIndexerWhenAvailable;

    var fileQuery = library.CreateFileQueryWithOptions(queryOptions);

    var fif = new Windows.Storage.BulkAccess.FileInformationFactory(
        fileQuery,
        Windows.Storage.FileProperties.ThumbnailMode.PicturesView,
        190,
        Windows.Storage.FileProperties.ThumbnailOptions.UseCurrentScale,
        false
        );

    var dataSource = fif.GetVirtualizedFilesVector();
    this.PicturesListView.ItemsSource = dataSource;
}

您通常會使用這個方法來建立檔案和資料夾資訊的唯讀檢視。You will typically use this approach to create a read-only view of file and folder info. 您可以建立檔案和資料夾屬性的雙向繫結,例如讓使用者在音樂檢視中給歌曲評分。You can create two-way bindings to the file and folder properties, for example to let users rate a song in a music view. 不過,所有變更都必須等到您呼叫適當的 SavePropertiesAsync 方法 (例如 MusicProperties.SavePropertiesAsync) 之後才能保留。However, any changes are not persisted until you call the appropriate SavePropertiesAsync method (for example, MusicProperties.SavePropertiesAsync). 您應該在項目失去焦點時認可變更,因為這會觸發選取項目重設。You should commit changes when the item loses focus because this triggers a selection reset.

請注意,使用這項技術的雙向繫結只適用於已編製索引的位置 (例如 音樂)。Note that two-way binding using this technique works only with indexed locations, such as Music. 您可以呼叫 FolderInformation.GetIndexedStateAsync 方法來判斷位置是否已編製索引。You can determine whether a location is indexed by calling the FolderInformation.GetIndexedStateAsync method.

另請注意,虛擬化向量可能會在填入某些項目的值之前先傳回 nullNote also that a virtualized vector can return null for some items before it populates their value. 例如,使用與虛擬化向量繫結之清單控制項的 SelectedItem 值之前,您應該先檢查是否有 null,或者改用 SelectedIndexFor example, you should check for null before you use the SelectedItem value of a list control bound to a virtualized vector, or use SelectedIndex instead.

繫結到依索引鍵分組的資料Binding to data grouped by a key

如果您取得一般項目集合 (例如書籍,以 BookSku 類別表示) 且使用常見的屬性作為索引鍵將項目分組 (例如 BookSku.AuthorName 屬性),則結果稱為分組資料。If you take a flat collection of items (books, for example, represented by a BookSku class) and you group the items by using a common property as a key (the BookSku.AuthorName property, for example) then the result is called grouped data. 資料分組之後就不再是一般集合。When you group data, it is no longer a flat collection. 群組資料是群組物件的集合,其中每個群組物件都有Grouped data is a collection of group objects, where each group object has

  • 索引鍵,以及a key, and
  • 項目的集合,其屬性符合該索引鍵。a collection of items whose property matches that key.

若要再次接受書籍範例,依作者姓名對書籍進行分組的結果將得出一個作者姓名群組的集合,其中每個群組都有To take the books example again, the result of grouping the books by author name results in a collection of author name groups where each group has

  • 索引鍵 (作者名稱),以及a key, which is an author name, and
  • BookSku 的集合,其 AuthorName 屬性符合群組的索引鍵。a collection of the BookSkus whose AuthorName property matches the group's key.

一般而言,若要顯示集合,您需要將項目控制項 (例如 ListViewGridView) 的 ItemsSource 直接繫結到傳回集合的屬性。In general, to display a collection, you bind the ItemsSource of an items control (such as ListView or GridView) directly to a property that returns a collection. 如果是一般項目集合,則不需要採取任何特別的動作。If that's a flat collection of items then you don't need to do anything special. 但如果是群組物件的集合 (例如繫結到分組資料時),則需要一個稱為 CollectionViewSource 的中繼物件的服務,此物件位於項目控制項和繫結來源之間。But if it's a collection of group objects (as it is when binding to grouped data) then you need the services of an intermediary object called a CollectionViewSource which sits between the items control and the binding source. 您需要將 CollectionViewSource 繫結到傳回分組資料的屬性,並將項目控制項繫結到 CollectionViewSourceYou bind the CollectionViewSource to the property that returns grouped data, and you bind the items control to the CollectionViewSource. CollectionViewSource 額外的好處是它可以追蹤目前的項目,可讓您將多個項目控制項全部繫結到相同的 CollectionViewSource,以保持同步。An extra value-add of a CollectionViewSource is that it keeps track of the current item, so you can keep more than one items control in sync by binding them all to the same CollectionViewSource. 您可以透過 CollectionViewSource.View 屬性所傳回的物件的 ICollectionView.CurrentItem 屬性,以程式設計方式存取目前的項目。You can also access the current item programmatically through the ICollectionView.CurrentItem property of the object returned by the CollectionViewSource.View property.

若要啟用 CollectionViewSource 的分組功能,請將 IsSourceGrouped 設定為 trueTo activate the grouping facility of a CollectionViewSource, set IsSourceGrouped to true. 不論您是否也需要設定 ItemsPath 屬性,這完全取決於您如何撰寫群組物件。Whether you also need to set the ItemsPath property depends on exactly how you author your group objects. 撰寫群組物件有兩種方式:「是一個群組」模式和「有一個群組」模式。There are two ways to author a group object: the "is-a-group" pattern, and the "has-a-group" pattern. 在「是一個群組」模式中,群組物件衍生自集合類型 (例如 List<T> ),因此群組物件本身實際上是項目群組。In the "is-a-group" pattern, the group object derives from a collection type (for example, List<T>), so the group object actually is itself the group of items. 使用這個模式時,您不需要設定 ItemsPathWith this pattern you do not need to set ItemsPath. 在「有一個群組」模式中,群組物件有集合類型 (例如 List<T> ) 的一或多個屬性,因此群組以屬性形式而「有一個」項目群組 (或以數個屬性的形式而有數個項目群組)。In the "has-a-group" pattern, the group object has one or more properties of a collection type (such as List<T>), so the group "has a" group of items in the form of a property (or several groups of items in the form of several properties). 使用這個模式時,您需要將 ItemsPath 設定為包含項目群組的屬性名稱。With this pattern you need to set ItemsPath to the name of the property that contains the group of items.

下列範例說明「有一個群組」模式。The example below illustrates the "has-a-group" pattern. 頁面類別有一個名為 ViewModel 的屬性,可傳回檢視模型的執行個體。The page class has a property named ViewModel, which returns an instance of our view model. CollectionViewSource 繫結至檢視模型的 Authors 屬性 (Authors 為群組物件的集合),也指定是 Author.BookSkus 屬性包含分組項目。The CollectionViewSource binds to the Authors property of the view model (Authors is the collection of group objects) and also specifies that it's the Author.BookSkus property that contains the grouped items. 最後,GridView 繫結至 CollectionViewSource,並定義其群組樣式以呈現群組中的項目。Finally, the GridView is bound to the CollectionViewSource, and has its group style defined so that it can render the items in groups.

<Page.Resources>
    <CollectionViewSource
    x:Name="AuthorHasACollectionOfBookSku"
    Source="{x:Bind ViewModel.Authors}"
    IsSourceGrouped="true"
    ItemsPath="BookSkus"/>
</Page.Resources>
...
<GridView
ItemsSource="{x:Bind AuthorHasACollectionOfBookSku}" ...>
    <GridView.GroupStyle>
        <GroupStyle
            HeaderTemplate="{StaticResource AuthorGroupHeaderTemplateWide}" ... />
    </GridView.GroupStyle>
</GridView>

「是一個群組」模式有兩種實作方式。You can implement the "is-a-group" pattern in one of two ways. 其中一種方法是撰寫您自己的群組類別。One way is to author your own group class. List<T> 衍生類別 (其中,T 是項目類型)。Derive the class from List<T> (where T is the type of the items). 例如,public class Author : List<BookSku>For example, public class Author : List<BookSku>. 第二種方法是使用 LINQ 運算式,從 BookSku 項目的相似屬性值,動態建立群組物件 (和群組類別)。The second way is to use a LINQ expression to dynamically create group objects (and a group class) from like property values of the BookSku items. 這個方法—維護一般項目清單並即時將它們組合在一起—常見於從雲端服務存取資料的 app。This approach—maintaining only a flat list of items and grouping them together on the fly—is typical of an app that accesses data from a cloud service. 這可讓您依作者或內容類型 (舉例),靈活地將書籍分組,而不需要 AuthorGenre 之類的特殊群組類別。You get the flexibility to group books by author or by genre (for example) without needing special group classes such as Author and Genre.

下列範例使用 LINQ 說明「是一個群組」模式。The example below illustrates the "is-a-group" pattern using LINQ. 這次我們依內容類型將書籍分組,並在群組標頭中顯示內容類型名稱。This time we group books by genre, displayed with the genre name in the group headers. 這是由群組 Key 值之參照中的 "Key" 屬性路徑所指示。This is indicated by the "Key" property path in reference to the group Key value.

using System.Linq;
...
private IOrderedEnumerable<IGrouping<string, BookSku>> genres;

public IOrderedEnumerable<IGrouping<string, BookSku>> Genres
{
    get
    {
        if (this.genres == null)
        {
            this.genres = from book in this.bookSkus
                          group book by book.genre into grp
                          orderby grp.Key
                          select grp;
        }
        return this.genres;
    }
}

請記住,當使用 {x:Bind} 和資料範本時,我們需要設定 x:DataType 值來表示繫結到的類型。Remember that when using {x:Bind} with data templates we need to indicate the type being bound to by setting an x:DataType value. 如果類型是泛型,則無法表達在標記中,我們需要在群組樣式標頭範本中改用 {Binding}If the type is generic then we can't express that in markup so we need to use {Binding} instead in the group style header template.

    <Grid.Resources>
        <CollectionViewSource x:Name="GenreIsACollectionOfBookSku"
        Source="{x:Bind Genres}"
        IsSourceGrouped="true"/>
    </Grid.Resources>
    <GridView ItemsSource="{x:Bind GenreIsACollectionOfBookSku}">
        <GridView.ItemTemplate x:DataType="local:BookTemplate">
            <DataTemplate>
                <TextBlock Text="{x:Bind Title}"/>
            </DataTemplate>
        </GridView.ItemTemplate>
        <GridView.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Key}"/>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </GridView.GroupStyle>
    </GridView>

SemanticZoom 控制項是讓使用者檢視及瀏覽分組資料的絕佳方式。A SemanticZoom control is a great way for your users to view and navigate grouped data. Bookstore2 範例 app 說明如何使用 SemanticZoomThe Bookstore2 sample app illustrates how to use the SemanticZoom. 在該 app 中,您可以檢視依作者分組的書籍清單 (放大檢視),也可以縮小來查看作者的捷徑清單 (縮小檢視)。In that app, you can view a list of books grouped by author (the zoomed-in view) or you can zoom out to see a jump list of authors (the zoomed-out view). 與捲動書籍清單相比,捷徑清單可提供更快速的瀏覽。The jump list affords much quicker navigation than scrolling through the list of books. 放大和縮小檢視實際上是繫結到相同 CollectionViewSourceListViewGridView 控制項。The zoomed-in and zoomed-out views are actually ListView or GridView controls bound to the same CollectionViewSource.

SemanticZoom 的圖例

當您繫結到階層式資料時—例如分類內的子分類—您可以選擇在 UI 中以一系列項目控制項來顯示階層式層級。When you bind to hierarchical data—such as subcategories within categories—you can choose to display the hierarchical levels in your UI with a series of items controls. 選取一個項目控制項會決定後續項目控制項的內容。A selection in one items control determines the contents of subsequent items controls. 您可以將每個清單繫結到它自身的 CollectionViewSource 並將 CollectionViewSource 執行個體一起繫結在鏈結中,使清單保持同步。You can keep the lists synchronized by binding each list to its own CollectionViewSource and binding the CollectionViewSource instances together in a chain. 這稱為主要/詳細資料 (或清單/詳細資料) 檢視。This is called a master/details (or list/details) view. 如需詳細資訊,請參閱如何繫結到階層式資料並建立主要/詳細資料檢視For more info, see How to bind to hierarchical data and create a master/details view.

診斷和偵錯資料繫結的問題Diagnosing and debugging data binding problems

繫結標記包含屬性的名稱 (針對 C#,有時還有欄位和方法)。Your binding markup contains the names of properties (and, for C#, sometimes fields and methods). 因此,當您重新命名屬性時,也需要變更任何參考它的繫結。So when you rename a property, you'll also need to change any binding that references it. 忘記這樣做會造成常見的資料繫結錯誤,而且您的 app 將無法編譯或無法正確執行。Forgetting to do that leads to a typical example of a data binding bug, and your app either won't compile or won't run correctly.

{x:Bind}{Binding} 建立的繫結物件在功能上大致相同。The binding objects created by {x:Bind} and {Binding} are largely functionally equivalent. 但是 {x:Bind} 有繫結來源的類型資訊,而且會在編譯階段產生原始程式碼。But {x:Bind} has type information for the binding source, and it generates source code at compile-time. 使用 {x:Bind} 時,可以對其餘的程式碼進行同樣的問題偵測。With {x:Bind} you get the same kind of problem detection that you get with the rest of your code. 這包括編譯時驗證您的繫結運算式,以及在產生做為頁面部分類別的原始程式碼中設定中斷點來偵錯。That includes compile-time validation of your binding expressions, and debugging by setting breakpoints in the source code generated as the partial class for your page. 您可以在 obj 資料夾的檔案中找到這些類別,名稱類似 (適用於 C#) <view name>.g.cs)。These classes can be found in the files in your obj folder, with names like (for C#) <view name>.g.cs). 如果繫結發生問題,請在 Microsoft Visual Studio 偵錯工具中開啟 [發生未處理的例外狀況時中斷] 。If you have a problem with a binding then turn on Break On Unhandled Exceptions in the Microsoft Visual Studio debugger. 偵錯工具會在那一刻中斷執行,讓您偵錯出了什麼問題。The debugger will break execution at that point, and you can then debug what has gone wrong. 對於繫結來源節點圖形的每個部分,{x:Bind} 產生的程式碼都採用相同的模式,您可以使用 呼叫堆疊 視窗中的資訊,協助您判斷導致問題的呼叫序列。The code generated by {x:Bind} follows the same pattern for each part of the graph of binding source nodes, and you can use the info in the Call Stack window to help determine the sequence of calls that led up to the problem.

{Binding} 沒有繫結來源的類型資訊。{Binding} does not have type information for the binding source. 但在附加偵錯工具的情況下執行您的應用程式時,所有繫結錯誤都會顯示在 Visual Studio 的 [輸出] 視窗中。But when you run your app with the debugger attached, any binding errors appear in the Output window in Visual Studio.

在程式碼中建立繫結Creating bindings in code

注意  此節只適用於 {Binding} (部分機器翻譯),因為您不能在程式碼中建立 {x:Bind} (部分機器翻譯) 繫結。Note  This section only applies to {Binding}, because you can't create {x:Bind} bindings in code. 不過,部分與 {x:Bind} 相同的優點可以利用 DependencyObject.RegisterPropertyChangedCallback 來達成,讓您能夠在任何相依性屬性上登錄變更通知。However, some of the same benefits of {x:Bind} can be achieved with DependencyObject.RegisterPropertyChangedCallback, which enables you to register for change notifications on any dependency property.

您也可以使用程序性程式碼來取代 XAML,將 UI 元素連結到資料。You can also connect UI elements to data using procedural code instead of XAML. 要這樣做,請建立新的 Binding 物件、設定適當的屬性,然後呼叫 FrameworkElement.SetBindingBindingOperations.SetBindingTo do this, create a new Binding object, set the appropriate properties, then call FrameworkElement.SetBinding or BindingOperations.SetBinding. 當您想在執行階段選擇繫結屬性值,或在多個控制項間共用單一繫結時,以程式設計方式建立繫結會很有用。Creating bindings programmatically is useful when you want to choose the binding property values at run-time or share a single binding among multiple controls. 不過,需注意在呼叫 SetBinding 之後,您就無法變更繫結屬性值。Note, however, that you cannot change the binding property values after you call SetBinding.

下列範例示範如何在程式碼中實作繫結。The following example shows how to implement a binding in code.

<TextBox x:Name="MyTextBox" Text="Text"/>
// Create an instance of the MyColors class 
// that implements INotifyPropertyChanged.
MyColors textcolor = new MyColors();

// Brush1 is set to be a SolidColorBrush with the value Red.
textcolor.Brush1 = new SolidColorBrush(Colors.Red);

// Set the DataContext of the TextBox MyTextBox.
MyTextBox.DataContext = textcolor;

// Create the binding and associate it with the text box.
Binding binding = new Binding() { Path = new PropertyPath("Brush1") };
MyTextBox.SetBinding(TextBox.ForegroundProperty, binding);
' Create an instance of the MyColors class 
' that implements INotifyPropertyChanged. 
Dim textcolor As New MyColors()

' Brush1 is set to be a SolidColorBrush with the value Red. 
textcolor.Brush1 = New SolidColorBrush(Colors.Red)

' Set the DataContext of the TextBox MyTextBox. 
MyTextBox.DataContext = textcolor

' Create the binding and associate it with the text box.
Dim binding As New Binding() With {.Path = New PropertyPath("Brush1")}
MyTextBox.SetBinding(TextBox.ForegroundProperty, binding)

{x:Bind} 和 {Binding} 功能比較{x:Bind} and {Binding} feature comparison

功能Feature {x:Bind}{x:Bind} {Binding}{Binding} 附註Notes
Path 是預設屬性Path is the default property {x:Bind a.b.c} {Binding a.b.c}
Path 屬性Path property {x:Bind Path=a.b.c} {Binding Path=a.b.c} 在 x:Bind 中,Path 預設以 Page 為根目錄,而不是 DataContext。In x:Bind, Path is rooted at the Page by default, not the DataContext.
索引編製程式Indexer {x:Bind Groups[2].Title} {Binding Groups[2].Title} 繫結至集合中指定的項目。Binds to the specified item in the collection. 支援僅整數索引。Only integer-based indexes are supported.
附加屬性Attached properties {x:Bind Button22.(Grid.Row)} {Binding Button22.(Grid.Row)} 使用括號指定附加屬性。Attached properties are specified using parentheses. 如果未在 XAML 命名空間中宣告屬性,則需要以 xml 命名空間為其加上首碼,而此命名空間應對應到文件最前面的程式碼命名空間。If the property is not declared in a XAML namespace, then prefix it with an xml namespace, which should be mapped to a code namespace at the head of the document.
轉型Casting {x:Bind groups[0].(data:SampleDataGroup.Title)} 不需要。Not needed. 使用括號指定轉型。Casts are specified using parentheses. 如果未在 XAML 命名空間中宣告屬性,則需要以 xml 命名空間為其加上首碼,而此命名空間應對應到文件最前面的程式碼命名空間。If the property is not declared in a XAML namespace, then prefix it with an xml namespace, which should be mapped to a code namespace at the head of the document.
ConverterConverter {x:Bind IsShown, Converter={StaticResource BoolToVisibility}} {Binding IsShown, Converter={StaticResource BoolToVisibility}} Converter 必須在 Page/ResourceDictionary 的根目錄或 App.xaml 中宣告。Converters must be declared at the root of the Page/ResourceDictionary, or in App.xaml.
ConverterParameter、ConverterLanguageConverterParameter, ConverterLanguage {x:Bind IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr} {Binding IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr} Converter 必須在 Page/ResourceDictionary 的根目錄或 App.xaml 中宣告。Converters must be declared at the root of the Page/ResourceDictionary, or in App.xaml.
TargetNullValueTargetNullValue {x:Bind Name, TargetNullValue=0} {Binding Name, TargetNullValue=0} 繫結運算式的分葉為 null 時使用。Used when the leaf of the binding expression is null. 使用單引號指定字串值。Use single quotes for a string value.
FallbackValueFallbackValue {x:Bind Name, FallbackValue='empty'} {Binding Name, FallbackValue='empty'} 繫結路徑的任何部分 (除了分葉) 為 null 時使用。Used when any part of the path for the binding (except for the leaf) is null.
ElementNameElementName {x:Bind slider1.Value} {Binding Value, ElementName=slider1} 您使用 {x:Bind} 繫結到欄位;Path 預設以 Page 為根目錄,任何具名的項目都可以透過它的欄位來存取。With {x:Bind} you're binding to a field; Path is rooted at the Page by default, so any named element can be accessed via its field.
RelativeSource:SelfRelativeSource: Self <Rectangle x:Name="rect1" Width="200" Height="{x:Bind rect1.Width}" ... /> <Rectangle Width="200" Height="{Binding Width, RelativeSource={RelativeSource Self}}" ... /> 使用 {X:Bind} 來命名元素,並在 Path 中使用它的名稱。With {x:Bind}, name the element and use its name in Path.
RelativeSource:TemplatedParentRelativeSource: TemplatedParent 不需要Not needed {Binding <path>, RelativeSource={RelativeSource TemplatedParent}} 使用 {x:Bind} ControlTemplate 上的 TargetType 表示繫結至父系範本。With {x:Bind} TargetType on ControlTemplate indicates binding to template parent. 針對 {Binding},一般範本繫結可以用在控制項範本中滿足大部分的用途。For {Binding} Regular template binding can be used in control templates for most uses. 但在需要使用轉換器或雙向繫結的情況下,請使用 TemplatedParent。<But use TemplatedParent where you need to use a converter, or a two-way binding.<
來源Source 不需要Not needed <ListView ItemsSource="{Binding Orders, Source={StaticResource MyData}}"/> 針對 {x:Bind},您可以直接使用已命名的元素,使用屬性或靜態路徑。For {x:Bind} you can directly use the named element, use a property or a static path.
模式Mode {x:Bind Name, Mode=OneWay} {Binding Name, Mode=TwoWay} Mode 可以是 OneTime、OneWay 或 TwoWay。Mode can be OneTime, OneWay, or TwoWay. {x:Bind} 預設為 OneTime。{Binding} 預設為 OneWay。{x:Bind} defaults to OneTime; {Binding} defaults to OneWay.
UpdateSourceTriggerUpdateSourceTrigger {x:Bind Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged} {Binding UpdateSourceTrigger=PropertyChanged} UpdateSourceTrigger 可以是 Default、LostFocus 或 PropertyChanged。UpdateSourceTrigger can be Default, LostFocus, or PropertyChanged. {x:Bind} 不支援 UpdateSourceTrigger=Explicit。{x:Bind} does not support UpdateSourceTrigger=Explicit. {x:Bind} 一律針對所有案例使用 PropertyChanged 行為,但 TextBox.Text 除外,其會使用 LostFocus 行為。{x:Bind} uses PropertyChanged behavior for all cases except TextBox.Text, where it uses LostFocus behavior.