WRLおよびBindableAttribute

Windowsランタイム用のUIアプリケーション開発の主なパターンはMVVMです。 ドキュメントには、バインディングオブジェクトはCLRオブジェクト、ユーザーインターフェイスオブジェクト、Windowsランタイムランタイムオブジェクト(BindableAttribute属性がある場合、またはICustomPropertyProviderを実装している場合)であると記載されています。



アプリケーションを開発する際の最も簡単なシナリオは、BindableAttribute属性をViewModelクラスに追加し、INotifyPropertyChangedインターフェイスを実装することです。 MIDL、C ++、およびWRLを使用してこれを行う方法に興味がある場合は、catにようこそ。



インターフェースの説明


idlファイルを作成し、インターフェイスを記述します。



import "inspectable.idl"; import "windows.ui.xaml.customattributes.idl"; import "windows.ui.xaml.data.idl"; #define VERSION 0x00000001 namespace DataBinding { interface INumber; interface INumberFactory; runtimeclass Number; } namespace DataBinding { [exclusiveto(Number)] [uuid(5b197688-2f57-4d01-92cd-a888f10dcd90)] [version(VERSION)] interface INumber : IInspectable { [propget] HRESULT Value([out, retval] INT32* value); [propput] HRESULT Value([in] INT32 value); } [exclusiveto(Number)] [uuid(baec017b-23ec-46d3-8d67-78bf0af1a9f1)] [version(VERSION)] interface INumberFactory : IInspectable { }; [activatable(1.0)] [bindable] [marshaling_behavior(agile)] [threading(both)] [version(VERSION)] runtimeclass Number { [default] interface INumber; interface Windows.UI.Xaml.Data.INotifyPropertyChanged; } }
      
      





DataBinding名前空間では、いくつかのオブジェクトを定義します。 1つ目は、クラスの専用インターフェイスです。 このインターフェイスには、読み取りおよび書き込み可能な単一の整数プロパティValueがあります。 2番目は、クラスオブジェクトを作成するためのファクトリインターフェイスです。 3番目は、2つのインターフェイスを実装するオブジェクトクラスです。 Numberクラスの起動可能な属性は、このクラスのオブジェクトがパラメーターをファクトリーに渡すことなく作成できることを示します。 バインド可能属性は、データバインディングメカニズムが機能するために必要なものとまったく同じBindableAttributeです。 この属性の説明はファイル「windows.ui.xaml.customattributes.idl」に含まれているため、このファイルはコードの2行目にインポートされます。 ファイルをコンパイルしたら、ヘッダーファイルを取得します。ヘッダーファイルは、ファイル内でコードと接続する必要があります。



インターフェイス実装


インターフェイスの記述に関するほとんどの作業は、ヘッダーファイルの作成時にMIDLコンパイラによって行われます。WRLを使用すると、マクロとテンプレートクラスを定義することにより、特定のインターフェイスの実装が簡素化されます。 有効なコードは次のようになります。



 #include <wrl.h> #include <wrl/wrappers/corewrappers.h> #include <wrl/event.h> #include "DataBinding_h.h" using ABI::DataBinding::INumber; using ABI::DataBinding::INumberFactory; using ABI::Windows::UI::Xaml::Data::IPropertyChangedEventArgsFactory; using ABI::Windows::UI::Xaml::Data::INotifyPropertyChanged; using ABI::Windows::UI::Xaml::Data::IPropertyChangedEventHandler; using ABI::Windows::UI::Xaml::Data::IPropertyChangedEventArgs; using ABI::Windows::UI::Xaml::Data::PropertyChangedEventArgs; using Microsoft::WRL::RuntimeClassFlags; using Microsoft::WRL::RuntimeClassType; using Microsoft::WRL::EventSource; using Microsoft::WRL::Make; using Microsoft::WRL::RuntimeClass; using Microsoft::WRL::ActivationFactory; using Microsoft::WRL::ComPtr; using Microsoft::WRL::Wrappers::HStringReference; class Number sealed : public RuntimeClass < RuntimeClassFlags<RuntimeClassType::WinRt>, INumber, INotifyPropertyChanged > { InspectableClass(RuntimeClass_DataBinding_Number, BaseTrust); private: INT32 _value; EventSource<IPropertyChangedEventHandler> _notifyEventSource; ComPtr<IPropertyChangedEventArgs> _valueChangedEventArgs; public: Number() : _value(0) { ComPtr<IPropertyChangedEventArgsFactory> propertyChangedEventArgsFactory; RoGetActivationFactory( HStringReference(RuntimeClass_Windows_UI_Xaml_Data_PropertyChangedEventArgs).Get(), ABI::Windows::UI::Xaml::Data::IID_IPropertyChangedEventArgsFactory, reinterpret_cast<void**>(propertyChangedEventArgsFactory.GetAddressOf())); ComPtr<IInspectable> inner; propertyChangedEventArgsFactory->CreateInstance( HStringReference(L"Value").Get(), nullptr, reinterpret_cast<IInspectable**>(_valueChangedEventArgs.GetAddressOf()), _valueChangedEventArgs.GetAddressOf()); } virtual HRESULT STDMETHODCALLTYPE get_Value(INT32* value) override { *value = _value; return S_OK; } virtual HRESULT STDMETHODCALLTYPE put_Value(INT32 value) override { _value = value; _notifyEventSource.InvokeAll(reinterpret_cast<IInspectable*>(this), _valueChangedEventArgs.Get()); return S_OK; } virtual HRESULT STDMETHODCALLTYPE add_PropertyChanged(IPropertyChangedEventHandler* handler, EventRegistrationToken* token) override { return _notifyEventSource.Add(handler, token); } virtual HRESULT STDMETHODCALLTYPE remove_PropertyChanged(EventRegistrationToken token) override { return _notifyEventSource.Remove(token); } }; class NumberFactory : public ActivationFactory < INumberFactory > { InspectableClassStatic(RuntimeClass_DataBinding_Number, BaseTrust); public: virtual HRESULT STDMETHODCALLTYPE ActivateInstance(IInspectable** instance) override { *instance = reinterpret_cast<IInspectable*>(Make<Number>().Detach()); return nullptr != *instance ? S_OK : E_OUTOFMEMORY; } }; ActivatableClassWithFactory(Number, NumberFactory);
      
      





このコードは2つのクラスを定義します。 最初は同じランタイムクラスNumberです。 INumberおよびINotifyPropertyChangedインターフェイスを実装し、純粋な仮想インターフェイスメソッドをオーバーライドします。 2番目は、Numberクラスのオブジェクトを作成するためのファクトリクラスです。 コードを正常にコンパイルするには、ヘッダーファイル「windows.ui.xaml.customattributes.h」が必要です。これは、インクルードのディレクティブがMIDLコンパイラーによってインクルードヘッダーファイルに自動的に挿入されるためです(ただし、このディレクティブをhファイルコードから手動で削除することもできます)。 $(WindowsSDK_MetadataPath)ディレクトリに作成しました。



確認する


コンポーネントコードをコンパイルした後、Windowsランタイムの任意のプロジェクトで使用できます。 私はC#プロジェクトでテストしました。 DataBindingを使用してオブジェクトのValueプロパティの値を表示する単純なビューを作成し、タイマーによってオブジェクトのプロパティの値を変更しました(3秒。そのため、要素はプロパティの初期値で表示する時間があります)。



All Articles