XAML 항목 컨트롤, C++/WinRT 컬렉션에 바인딩XAML items controls; bind to a C++/WinRT collection

XAML 항목에 효과적으로 바인딩할 수 있는 컬렉션은 식별할 수 있는(observable) 컬렉션이라고 합니다.A collection that can be effectively bound to a XAML items control is known as an observable collection. 이 아이디어는 ‘관찰자 패턴’이라고 알려진 소프트웨어 디자인 패턴에 바탕을 두고 있습니다. This idea is based on the software design pattern known as the observer pattern. 이 항목에서는 C++/WinRT에서 관찰 가능한 컬렉션을 구현하는 방법과 XAML 항목 컨트롤을 이 속성에 바인딩하는 방법을 보여줍니다(배경 정보는 데이터 바인딩 참조).This topic shows how to implement observable collections in C++/WinRT, and how to bind XAML items controls to them (for background info, see Data binding).

이 항목의 과정을 따르려면 먼저 XAML 컨트롤, C++/WinRT 속성에 바인딩에 설명된 프로젝트를 만드는 것이 좋습니다.If you want to follow along with this topic, then we recommend that you first create the project that's described in XAML controls; bind to a C++/WinRT property. 이 항목에서는 해당 프로젝트에 더 많은 코드를 추가하며 이 코드는 이 항목에서 설명하는 개념에 추가됩니다.This topic adds more code to that project, and it adds to the concepts explained in that topic.

중요

C++/WinRT를 사용해 런타임 클래스를 사용하거나 작성하는 방법을 더욱 쉽게 이해할 수 있는 필수 개념과 용어에 대해서는 C++/WinRT를 통한 API 사용C++/WinRT를 통한 API 작성을 참조하세요.For 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 collection?

컬렉션을 나타내는 런타임 클래스에서 요소 추가 또는 제거 시 IObservableVector<T>::VectorChanged 이벤트가 발생하도록 선택하는 경우, 이 런타임 클래스는 관찰 가능한 컬렉션이 됩니다.If a runtime class that represents a collection chooses to raise the IObservableVector<T>::VectorChanged event whenever an element is added to it or removed from it, then the runtime class is an observable collection. XAML 항목 컨트롤은 업데이트된 컬렉션을 가져와 현재 요소를 표시하도록 스스로 업데이트함으로써 이러한 이벤트에 바인딩하여 처리할 수 있습니다.A XAML items control can bind to, and handle, these events by retrieving the updated collection and then updating itself to show the current elements.

참고

프로젝트 템플릿 및 빌드 지원을 함께 제공하는 C++/WinRT Visual Studio 확장(VSIX) 및 NuGet 패키지를 설치하고 사용하는 방법에 대한 자세한 내용은 Visual Studio의 C++/WinRT 지원을 참조하세요.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.

BookSkus 컬렉션을 BookstoreViewModel에 추가Add a BookSkus collection to BookstoreViewModel

XAML 컨트롤, C++/WinRT 속성에 바인딩에서는 BookSku 형식의 속성을 기본 보기 모델에 추가했습니다.In XAML controls; bind to a C++/WinRT property, we added a property of type BookSku to our main view model. 이 단계에서는 winrt::single_threaded_observable_vector 팩터리 함수 템플릿을 사용하여 동일한 보기 모델에서 BookSku의 관찰 가능한 컬렉션을 구현하도록 도와줍니다.In this step, we'll use the winrt::single_threaded_observable_vector factory function template to help us implement an observable collection of BookSku on the same view model.

BookstoreViewModel.idl에서 새 속성을 선언합니다.Declare a new property in BookstoreViewModel.idl.

// BookstoreViewModel.idl
...
runtimeclass BookstoreViewModel
{
    BookSku BookSku{ get; };
    Windows.Foundation.Collections.IObservableVector<BookSku> BookSkus{ get; };
}
...

참고

위의 MIDL 3.0 목록에서 BookSkus 속성의 형식은 BookSkuIObservableVector입니다.In the MIDL 3.0 listing above, note that the type of the BookSkus property is IObservableVector of BookSku. 이 항목의 다음 섹션에서는 ListBox의 항목 원본을 BookSkus에 바인딩합니다.In the next section of this topic, we'll be binding the items source of a ListBox to BookSkus. 목록 상자는 항목 컨트롤이며, ItemsControl.ItemsSource 속성을 제대로 설정하려면 IObservableVector 또는 IVector 형식 값으로 설정하거나 IBindableObservableVector와 같은 상호 운용성 형식 값으로 설정해야 합니다.A list box is an items control, and to correctly set the ItemsControl.ItemsSource property, you need to set it to a value of type IObservableVector, or IVector, or of an interoperability type such as IBindableObservableVector.

경고

이 항목에 표시된 코드는 C++/WinRT 버전 2.0.190530.8 이상에 적용됩니다.The code shown in this topic applies to C++/WinRT version 2.0.190530.8 and higher. 이전 버전을 사용하는 경우 표시된 코드에 몇 가지 사소한 변경을 해야 합니다.If you're using an earlier version, then you'll need to make some minor tweaks to the code shown. 위의 MIDL 3.0 목록에서 BookSkus 속성을 IInspectableIObservableVector로 변경합니다.In the MIDL 3.0 listing above, change the BookSkus property to IObservableVector of IInspectable. 그 다음, 구현에서도 IInspectable(BookSku 대신)을 사용합니다.And then use IInspectable (instead of BookSku) in your implementation, too.

저장 후 빌드합니다.Save and build. \Bookstore\Bookstore\Generated Files\sources 폴더의 BookstoreViewModel.hBookstoreViewModel.cpp에서 접근자 스텁을 복사합니다. 자세한 내용은 이전 항목인 XAML 컨트롤, C++/WinRT 속성 바인딩을 참조하세요.Copy the accessor stubs from BookstoreViewModel.h and BookstoreViewModel.cpp in the \Bookstore\Bookstore\Generated Files\sources folder (for more details, see the previous topic, XAML controls; bind to a C++/WinRT property). 다음과 같이 접근자 스텁을 구현합니다.Implement those accessor stubs like this.

// BookstoreViewModel.h
...
struct BookstoreViewModel : BookstoreViewModelT<BookstoreViewModel>
{
    BookstoreViewModel();

    Bookstore::BookSku BookSku();

    Windows::Foundation::Collections::IObservableVector<Bookstore::BookSku> BookSkus();

private:
    Bookstore::BookSku m_bookSku{ nullptr };
    Windows::Foundation::Collections::IObservableVector<Bookstore::BookSku> m_bookSkus;
};
...
// BookstoreViewModel.cpp
...
BookstoreViewModel::BookstoreViewModel()
{
    m_bookSku = winrt::make<Bookstore::implementation::BookSku>(L"Atticus");
    m_bookSkus = winrt::single_threaded_observable_vector<Bookstore::BookSku>();
    m_bookSkus.Append(m_bookSku);
}

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

Windows::Foundation::Collections::IObservableVector<Bookstore::BookSku> BookstoreViewModel::BookSkus()
{
    return m_bookSkus;
}
...

ListBox를 BookSkus 속성에 바인딩Bind a ListBox to the BookSkus property

MainPage.xaml을 엽니다. 여기에는 기본 UI 페이지에 사용할 XAML 태그가 포함되어 있습니다.Open MainPage.xaml, which contains the XAML markup for our main UI page. 다음 태그를 Button과 동일한 StackPanel 내부에 추가합니다.Add the following markup inside the same StackPanel as the Button.

<ListBox ItemsSource="{x:Bind MainViewModel.BookSkus}">
    <ItemsControl.ItemTemplate>
        <DataTemplate x:DataType="local:BookSku">
            <TextBlock Text="{x:Bind Title, Mode=OneWay}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ListBox>

MainPage.cpp에서 하나의 코드 줄을 Click 이벤트 처리기에 추가하여 책을 컬렉션에 추가합니다.In MainPage.cpp, add a line of code to the Click event handler to append a book to the collection.

// MainPage.cpp
...
void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    MainViewModel().BookSku().Title(L"To Kill a Mockingbird");
    MainViewModel().BookSkus().Append(winrt::make<Bookstore::implementation::BookSku>(L"Moby Dick"));
}
...

이제 프로젝트를 빌드하고 실행합니다.Now build and run the project. 단추를 클릭하여 Click 이벤트 처리기를 실행합니다.Click the button to execute the Click event handler. 앞에서 Append 구현이 UI가 컬렉션의 변경 사실을 알 수 있도록 이벤트를 발생시키고, 그러면 ListBox가 컬렉션을 다시 쿼리하여 Items 값을 업데이트하는 것을 확인했습니다.We saw that the implementation of Append raises an event to let the UI know that the collection has changed; and the ListBox re-queries the collection to update its own Items value. 이와 마찬가지로 책 중 하나의 제목이 변경되면 변경된 해당 제목이 단추와 목록 상자 모두에 반영됩니다.Just as before, the title of one of the books changes; and that title change is reflected both on the button and in the list box.

중요 APIImportant APIs