diff --git a/TestComponentCSharp/Class.cpp b/TestComponentCSharp/Class.cpp index 922d0530f..9cfff9fe0 100644 --- a/TestComponentCSharp/Class.cpp +++ b/TestComponentCSharp/Class.cpp @@ -7,6 +7,7 @@ using namespace std::chrono; using namespace winrt; using namespace Windows::Foundation; using namespace Collections; +using namespace Microsoft::UI::Xaml::Data; using namespace Microsoft::UI::Xaml::Interop; using Windows::UI::Xaml::Interop::TypeName; @@ -102,6 +103,27 @@ namespace winrt::TestComponentCSharp::implementation } }; + struct data_errors_changed_event_args : implements + { + data_errors_changed_event_args(winrt::hstring name) : + m_name(name) + { + } + + hstring PropertyName() const + { + return m_name; + } + + void PropertyName(param::hstring const& name) + { + m_name = name; + } + + private: + winrt::hstring m_name; + }; + Class::Class() : Class(0, L"") { @@ -393,11 +415,11 @@ namespace winrt::TestComponentCSharp::implementation { _objectChanged.remove(token); } - Windows::Foundation::Collections::IIterable Class::ObjectIterableProperty() + IIterable Class::ObjectIterableProperty() { return _objectIterable; } - void Class::ObjectIterableProperty(Windows::Foundation::Collections::IIterable const& value) + void Class::ObjectIterableProperty(IIterable const& value) { for (auto element : value) { @@ -412,7 +434,7 @@ namespace winrt::TestComponentCSharp::implementation { _objectIterable = provideObjectIterable(); } - winrt::event_token Class::ObjectIterablePropertyChanged(Windows::Foundation::EventHandler> const& handler) + winrt::event_token Class::ObjectIterablePropertyChanged(EventHandler> const& handler) { return _objectIterableChanged.add(handler); } @@ -789,22 +811,22 @@ namespace winrt::TestComponentCSharp::implementation _point = value; } - Windows::Foundation::Rect Class::RectProperty() + Rect Class::RectProperty() { return _rect; } - void Class::RectProperty(Windows::Foundation::Rect const& value) + void Class::RectProperty(Rect const& value) { _rect = value; } - Windows::Foundation::Size Class::SizeProperty() + Size Class::SizeProperty() { return _size; } - void Class::SizeProperty(Windows::Foundation::Size const& value) + void Class::SizeProperty(Size const& value) { _size = value; } @@ -891,59 +913,59 @@ namespace winrt::TestComponentCSharp::implementation { _matrix3D = value; } - Windows::Foundation::Numerics::float3x2 Class::Matrix3x2Property() + Numerics::float3x2 Class::Matrix3x2Property() { return _matrix3x2; } - void Class::Matrix3x2Property(Windows::Foundation::Numerics::float3x2 const& value) + void Class::Matrix3x2Property(Numerics::float3x2 const& value) { _matrix3x2 = value; } - Windows::Foundation::Numerics::float4x4 Class::Matrix4x4Property() + Numerics::float4x4 Class::Matrix4x4Property() { return _matrix4x4; } - void Class::Matrix4x4Property(Windows::Foundation::Numerics::float4x4 const& value) + void Class::Matrix4x4Property(Numerics::float4x4 const& value) { _matrix4x4 = value; } - Windows::Foundation::Numerics::plane Class::PlaneProperty() + Numerics::plane Class::PlaneProperty() { return _plane; } - void Class::PlaneProperty(Windows::Foundation::Numerics::plane const& value) + void Class::PlaneProperty(Numerics::plane const& value) { _plane = value; } - Windows::Foundation::Numerics::quaternion Class::QuaternionProperty() + Numerics::quaternion Class::QuaternionProperty() { return _quaternion; } - void Class::QuaternionProperty(Windows::Foundation::Numerics::quaternion const& value) + void Class::QuaternionProperty(Numerics::quaternion const& value) { _quaternion = value; } - Windows::Foundation::Numerics::float2 Class::Vector2Property() + Numerics::float2 Class::Vector2Property() { return _vector2; } - void Class::Vector2Property(Windows::Foundation::Numerics::float2 const& value) + void Class::Vector2Property(Numerics::float2 const& value) { _vector2 = value; } - Windows::Foundation::Numerics::float3 Class::Vector3Property() + Numerics::float3 Class::Vector3Property() { return _vector3; } - void Class::Vector3Property(Windows::Foundation::Numerics::float3 const& value) + void Class::Vector3Property(Numerics::float3 const& value) { _vector3 = value; } - Windows::Foundation::Numerics::float4 Class::Vector4Property() + Numerics::float4 Class::Vector4Property() { return _vector4; } - void Class::Vector4Property(Windows::Foundation::Numerics::float4 const& value) + void Class::Vector4Property(Numerics::float4 const& value) { _vector4 = value; } @@ -1179,7 +1201,7 @@ namespace winrt::TestComponentCSharp::implementation return type.Name; } - Windows::Foundation::IInspectable Class::EmptyString() + IInspectable Class::EmptyString() { return winrt::box_value(hstring{}); } @@ -1202,4 +1224,29 @@ namespace winrt::TestComponentCSharp::implementation { return winrt::make(); } + + // INotifyDataErrorInfo + bool Class::HasErrors() + { + return true; + } + winrt::event_token Class::ErrorsChanged(EventHandler const& handler) + { + return _dataErrorsChanged.add(handler); + } + void Class::ErrorsChanged(winrt::event_token const& token) noexcept + { + _dataErrorsChanged.remove(token); + } + IIterable Class::GetErrors(hstring const& propertyName) + { + return _objectIterable; + } + void Class::RaiseDataErrorChanged() + { + auto mock = make(L"name"); + DataErrorsChangedEventArgs args(detach_abi(mock), take_ownership_from_abi_t()); + _dataErrorsChanged(*this, args); + } } + diff --git a/TestComponentCSharp/Class.h b/TestComponentCSharp/Class.h index bbb682a8d..75d03cc0f 100644 --- a/TestComponentCSharp/Class.h +++ b/TestComponentCSharp/Class.h @@ -318,6 +318,13 @@ namespace winrt::TestComponentCSharp::implementation void ReadWriteProperty(int32_t value); //hstring DistinctProperty(); //void DistinctProperty(hstring const& value); + + winrt::event> _dataErrorsChanged; + bool HasErrors(); + winrt::event_token ErrorsChanged(Windows::Foundation::EventHandler const& handler); + void ErrorsChanged(winrt::event_token const& token) noexcept; + Windows::Foundation::Collections::IIterable GetErrors(hstring const& propertyName); + void RaiseDataErrorChanged(); }; } diff --git a/TestComponentCSharp/TestComponentCSharp.idl b/TestComponentCSharp/TestComponentCSharp.idl index e44598fa0..2b357e975 100644 --- a/TestComponentCSharp/TestComponentCSharp.idl +++ b/TestComponentCSharp/TestComponentCSharp.idl @@ -101,6 +101,7 @@ namespace TestComponentCSharp //, IArtist , IProperties1 , IProperties2 + , Microsoft.UI.Xaml.Data.INotifyDataErrorInfo //, Windows.Foundation.Collections.IVector //, Windows.Foundation.Collections.IMap { @@ -312,6 +313,9 @@ namespace TestComponentCSharp // Interface projections static IProperties1 NativeProperties1 { get; }; + + // INotifyDataErrorInfo + void RaiseDataErrorChanged(); } [threading(sta), marshaling_behavior(standard)] diff --git a/UnitTest/TestComponentCSharp_Tests.cs b/UnitTest/TestComponentCSharp_Tests.cs index 61f8b00c3..172e023a0 100644 --- a/UnitTest/TestComponentCSharp_Tests.cs +++ b/UnitTest/TestComponentCSharp_Tests.cs @@ -149,9 +149,17 @@ public void TestEvents() TestObject.InvokeCollectionEvent(TestObject, collection0, collection1); events_expected++; - Assert.Equal(events_received, events_expected); - } + TestObject.ErrorsChanged += (object sender, System.ComponentModel.DataErrorsChangedEventArgs e) => + { + events_received++; + Assert.Equal("name", e.PropertyName); + }; + TestObject.RaiseDataErrorChanged(); + events_expected++; + Assert.Equal(events_received, events_expected); + } + [Fact] public void TestKeyValuePair() { diff --git a/WinRT.Runtime/Projections.cs b/WinRT.Runtime/Projections.cs index 844e60026..43bf4adba 100644 --- a/WinRT.Runtime/Projections.cs +++ b/WinRT.Runtime/Projections.cs @@ -30,8 +30,10 @@ static Projections() RegisterCustomAbiTypeMappingNoLock(typeof(Exception), typeof(ABI.System.Exception), "Windows.Foundation.HResult"); RegisterCustomAbiTypeMappingNoLock(typeof(TimeSpan), typeof(ABI.System.TimeSpan), "Windows.Foundation.TimeSpan"); RegisterCustomAbiTypeMappingNoLock(typeof(Uri), typeof(ABI.System.Uri), "Windows.Foundation.Uri", isRuntimeClass: true); + RegisterCustomAbiTypeMappingNoLock(typeof(DataErrorsChangedEventArgs), typeof(ABI.System.ComponentModel.DataErrorsChangedEventArgs), "Microsoft.UI.Xaml.Data.DataErrorsChangedEventArgs", isRuntimeClass: true); RegisterCustomAbiTypeMappingNoLock(typeof(PropertyChangedEventArgs), typeof(ABI.System.ComponentModel.PropertyChangedEventArgs), "Microsoft.UI.Xaml.Data.PropertyChangedEventArgs", isRuntimeClass: true); RegisterCustomAbiTypeMappingNoLock(typeof(PropertyChangedEventHandler), typeof(ABI.System.ComponentModel.PropertyChangedEventHandler), "Microsoft.UI.Xaml.Data.PropertyChangedEventHandler"); + RegisterCustomAbiTypeMappingNoLock(typeof(INotifyDataErrorInfo), typeof(ABI.System.ComponentModel.INotifyDataErrorInfo), "Microsoft.UI.Xaml.Data.INotifyDataErrorInfo"); RegisterCustomAbiTypeMappingNoLock(typeof(INotifyPropertyChanged), typeof(ABI.System.ComponentModel.INotifyPropertyChanged), "Microsoft.UI.Xaml.Data.INotifyPropertyChanged"); RegisterCustomAbiTypeMappingNoLock(typeof(ICommand), typeof(ABI.System.Windows.Input.ICommand), "Microsoft.UI.Xaml.Interop.ICommand"); RegisterCustomAbiTypeMappingNoLock(typeof(EventHandler<>), typeof(ABI.System.EventHandler<>), "Windows.Foundation.EventHandler`1"); diff --git a/WinRT.Runtime/Projections/DataErrorsChangedEventArgs.cs b/WinRT.Runtime/Projections/DataErrorsChangedEventArgs.cs new file mode 100644 index 000000000..570fed9f4 --- /dev/null +++ b/WinRT.Runtime/Projections/DataErrorsChangedEventArgs.cs @@ -0,0 +1,142 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Runtime.InteropServices; +using System.Text; +using WinRT; +using WinRT.Interop; + + +namespace ABI.Microsoft.UI.Xaml.Data +{ + [Guid("D026DD64-5F26-5F15-A86A-0DEC8A431796")] + [StructLayout(LayoutKind.Sequential)] + internal unsafe struct IDataErrorsChangedEventArgsVftbl + { + internal IInspectable.Vftbl IInspectableVftbl; + + private void* _get_PropertyName_0; + public delegate* unmanaged[Stdcall] get_PropertyName_0 => (delegate* unmanaged[Stdcall])_get_PropertyName_0; + + private void* _put_PropertyName_1; + public delegate* unmanaged[Stdcall] put_PropertyName_1 => (delegate* unmanaged[Stdcall])_put_PropertyName_1; + } + + + [global::WinRT.ObjectReferenceWrapper(nameof(_obj))] + [Guid("62D0BD1E-B85F-5FCC-842A-7CB0DDA37FE5")] + internal unsafe class WinRTDataErrorsChangedEventArgsRuntimeClassFactory + { + [Guid("62D0BD1E-B85F-5FCC-842A-7CB0DDA37FE5")] + [StructLayout(LayoutKind.Sequential)] + public struct Vftbl + { + internal IInspectable.Vftbl IInspectableVftbl; + private void* _CreateInstance_0; + public delegate* unmanaged[Stdcall] CreateInstance_0 => (delegate* unmanaged[Stdcall])_CreateInstance_0; + } + public static ObjectReference FromAbi(IntPtr thisPtr) => ObjectReference.FromAbi(thisPtr); + + public static implicit operator WinRTDataErrorsChangedEventArgsRuntimeClassFactory(IObjectReference obj) => (obj != null) ? new WinRTDataErrorsChangedEventArgsRuntimeClassFactory(obj) : null; + public static implicit operator WinRTDataErrorsChangedEventArgsRuntimeClassFactory(ObjectReference obj) => (obj != null) ? new WinRTDataErrorsChangedEventArgsRuntimeClassFactory(obj) : null; + protected readonly ObjectReference _obj; + public IntPtr ThisPtr => _obj.ThisPtr; + public ObjectReference AsInterface() => _obj.As(); + public A As() => _obj.AsType(); + public WinRTDataErrorsChangedEventArgsRuntimeClassFactory(IObjectReference obj) : this(obj.As()) { } + public WinRTDataErrorsChangedEventArgsRuntimeClassFactory(ObjectReference obj) + { + _obj = obj; + } + + public unsafe IObjectReference CreateInstance(string name) + { + MarshalString __name = default; + IntPtr __retval = default; + try + { + __name = MarshalString.CreateMarshaler(name); + global::WinRT.ExceptionHelpers.ThrowExceptionForHR(_obj.Vftbl.CreateInstance_0(ThisPtr, MarshalString.GetAbi(__name), &__retval)); + return ObjectReference.Attach(ref __retval); + } + finally + { + MarshalString.DisposeMarshaler(__name); + MarshalInspectable.DisposeAbi(__retval); + } + } + } +} + +namespace ABI.System.ComponentModel +{ + [EditorBrowsable(EditorBrowsableState.Never)] + [StructLayout(LayoutKind.Sequential)] + public unsafe struct DataErrorsChangedEventArgs + { + private static WeakLazy _factory = new WeakLazy(); + + private class ActivationFactory : BaseActivationFactory + { + public ActivationFactory() : base("Microsoft.UI.Xaml.Data", "Microsoft.UI.Xaml.Data.DataErrorsChangedEventArgs") + { + } + } + + public static IObjectReference CreateMarshaler(global::System.ComponentModel.DataErrorsChangedEventArgs value) + { + if (value is null) + { + return null; + } + + ABI.Microsoft.UI.Xaml.Data.WinRTDataErrorsChangedEventArgsRuntimeClassFactory factory = _factory.Value._As(); + return factory.CreateInstance(value.PropertyName); + } + + public static IntPtr GetAbi(IObjectReference m) => m?.ThisPtr ?? IntPtr.Zero; + + public static global::System.ComponentModel.DataErrorsChangedEventArgs FromAbi(IntPtr ptr) + { + if (ptr == IntPtr.Zero) + { + return null; + } + + using var args = ObjectReference.FromAbi(ptr); + IntPtr propertyName = IntPtr.Zero; + try + { + ExceptionHelpers.ThrowExceptionForHR(args.Vftbl.get_PropertyName_0(args.ThisPtr, &propertyName)); + return new global::System.ComponentModel.DataErrorsChangedEventArgs(MarshalString.FromAbi(propertyName)); + } + finally + { + MarshalString.DisposeAbi(propertyName); + } + } + + public static unsafe void CopyManaged(global::System.ComponentModel.DataErrorsChangedEventArgs o, IntPtr dest) + { + using var objRef = CreateMarshaler(o); + *(IntPtr*)dest.ToPointer() = objRef?.GetRef() ?? IntPtr.Zero; + } + + public static IntPtr FromManaged(global::System.ComponentModel.DataErrorsChangedEventArgs value) + { + if (value is null) + { + return IntPtr.Zero; + } + return CreateMarshaler(value).GetRef(); + } + + public static void DisposeMarshaler(IObjectReference m) { m?.Dispose(); } + public static void DisposeAbi(IntPtr abi) { using var objRef = ObjectReference.Attach(ref abi); } + + public static string GetGuidSignature() + { + return "rc(Microsoft.UI.Xaml.Data.DataErrorsChangedEventArgs;{d026dd64-5f26-5f15-a86a-0dec8a431796})"; + } + } +} diff --git a/WinRT.Runtime/Projections/INotifyDataErrorInfo.cs b/WinRT.Runtime/Projections/INotifyDataErrorInfo.cs new file mode 100644 index 000000000..256f89feb --- /dev/null +++ b/WinRT.Runtime/Projections/INotifyDataErrorInfo.cs @@ -0,0 +1,214 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; +using System.Linq; +using WinRT; +using WinRT.Interop; + +namespace ABI.System.ComponentModel +{ + [global::WinRT.ObjectReferenceWrapper(nameof(_obj)), global::System.ComponentModel.EditorBrowsable(global::System.ComponentModel.EditorBrowsableState.Never)] + [Guid("0EE6C2CC-273E-567D-BC0A-1DD87EE51EBA")] + public unsafe class INotifyDataErrorInfo : global::System.ComponentModel.INotifyDataErrorInfo + { + [Guid("0EE6C2CC-273E-567D-BC0A-1DD87EE51EBA")] + public struct Vftbl + { + internal IInspectable.Vftbl IInspectableVftbl; +#if NETSTANDARD2_0 + private void* _get_HasErrors_0; + public delegate* unmanaged[Stdcall] get_HasErrors_0 { get => (delegate* unmanaged[Stdcall])_get_HasErrors_0; set => _get_HasErrors_0 = (void*)value; } + private void* _add_ErrorsChanged_1; + public delegate* unmanaged[Stdcall] add_ErrorsChanged_1 { get => (delegate* unmanaged[Stdcall])_add_ErrorsChanged_1; set => _add_ErrorsChanged_1 = (void*)value; } + private void* _remove_ErrorsChanged_2; + public delegate* unmanaged[Stdcall] remove_ErrorsChanged_2 { get => (delegate* unmanaged[Stdcall])_remove_ErrorsChanged_2; set => _remove_ErrorsChanged_2 = (void*)value; } + private void* _GetErrors_3; + public delegate* unmanaged[Stdcall] GetErrors_3 { get => (delegate* unmanaged[Stdcall])_GetErrors_3; set => _GetErrors_3 = (void*)value; } +#else + private delegate* _get_HasErrors_0; + public delegate* unmanaged[Stdcall] get_HasErrors_0 { get => (delegate* unmanaged[Stdcall])_get_HasErrors_0; set => _get_HasErrors_0 = (delegate*)value; } + private delegate* _add_ErrorsChanged_1; + public delegate* unmanaged[Stdcall] add_ErrorsChanged_1 { get => (delegate* unmanaged[Stdcall])_add_ErrorsChanged_1; set => _add_ErrorsChanged_1 = (delegate*)value; } + private delegate* _remove_ErrorsChanged_2; + public delegate* unmanaged[Stdcall] remove_ErrorsChanged_2 { get => (delegate* unmanaged[Stdcall])_remove_ErrorsChanged_2; set => _remove_ErrorsChanged_2 = (delegate*)value; } + private delegate* _GetErrors_3; + public delegate* unmanaged[Stdcall] GetErrors_3 { get => (delegate* unmanaged[Stdcall])_GetErrors_3; set => _GetErrors_3 = (delegate*)value; } +#endif + + public static readonly IntPtr AbiToProjectionVftablePtr; + +#if NETSTANDARD2_0 + private static Delegate[] DelegateCache = new Delegate[4]; +#endif + + static unsafe Vftbl() + { + AbiToProjectionVftablePtr = ComWrappersSupport.AllocateVtableMemory(typeof(Vftbl), Marshal.SizeOf() + sizeof(IntPtr) * 4); + (*(Vftbl*)AbiToProjectionVftablePtr) = new Vftbl + { + IInspectableVftbl = global::WinRT.IInspectable.Vftbl.AbiToProjectionVftable, +#if NETSTANDARD2_0 + _get_HasErrors_0 = (void*)Marshal.GetFunctionPointerForDelegate(DelegateCache[0] = new INotifyDataErrorInfo_Delegates.get_HasErrors_0(Do_Abi_get_HasErrors_0)).ToPointer(), + _add_ErrorsChanged_1 = (void*)Marshal.GetFunctionPointerForDelegate(DelegateCache[1] = new INotifyDataErrorInfo_Delegates.add_ErrorsChanged_1(Do_Abi_add_ErrorsChanged_1)).ToPointer(), + _remove_ErrorsChanged_2 = (void*)Marshal.GetFunctionPointerForDelegate(DelegateCache[2] = new INotifyDataErrorInfo_Delegates.remove_ErrorsChanged_2(Do_Abi_remove_ErrorsChanged_2)).ToPointer(), + _GetErrors_3 = (void*)Marshal.GetFunctionPointerForDelegate(DelegateCache[3] = new INotifyDataErrorInfo_Delegates.GetErrors_3(Do_Abi_GetErrors_3)).ToPointer() +#else + _get_HasErrors_0 = &Do_Abi_get_HasErrors_0, + _add_ErrorsChanged_1 = &Do_Abi_add_ErrorsChanged_1, + _remove_ErrorsChanged_2 = &Do_Abi_remove_ErrorsChanged_2, + _GetErrors_3 = &Do_Abi_GetErrors_3 +#endif + }; + } + +#if !NETSTANDARD2_0 + [UnmanagedCallersOnly] +#endif + private static unsafe int Do_Abi_GetErrors_3(IntPtr thisPtr, IntPtr propertyName, IntPtr* result) + { + global::System.Collections.Generic.IEnumerable __result = default; + + *result = default; + + try + { + __result = global::WinRT.ComWrappersSupport.FindObject(thisPtr).GetErrors(MarshalString.FromAbi(propertyName)).OfType(); + *result = global::ABI.System.Collections.Generic.IEnumerable.FromManaged(__result); + + } + catch (global::System.Exception __exception__) + { + global::WinRT.ExceptionHelpers.SetErrorInfo(__exception__); + return global::WinRT.ExceptionHelpers.GetHRForException(__exception__); + } + return 0; + } + +#if !NETSTANDARD2_0 + [UnmanagedCallersOnly] +#endif + private static unsafe int Do_Abi_get_HasErrors_0(IntPtr thisPtr, byte* value) + { + bool __value = default; + + *value = default; + + try + { + __value = global::WinRT.ComWrappersSupport.FindObject(thisPtr).HasErrors; + *value = (byte)(__value ? 1 : 0); + + } + catch (global::System.Exception __exception__) + { + global::WinRT.ExceptionHelpers.SetErrorInfo(__exception__); + return global::WinRT.ExceptionHelpers.GetHRForException(__exception__); + } + return 0; + } + private static global::System.Runtime.CompilerServices.ConditionalWeakTable>> _ErrorsChanged_TokenTables = new global::System.Runtime.CompilerServices.ConditionalWeakTable>>(); + +#if !NETSTANDARD2_0 + [UnmanagedCallersOnly] +#endif + private static unsafe int Do_Abi_add_ErrorsChanged_1(IntPtr thisPtr, IntPtr handler, global::WinRT.EventRegistrationToken* token) + { + *token = default; + try + { + var __this = global::WinRT.ComWrappersSupport.FindObject(thisPtr); + var __handler = global::ABI.System.EventHandler.FromAbi(handler); + *token = _ErrorsChanged_TokenTables.GetOrCreateValue(__this).AddEventHandler(__handler); + __this.ErrorsChanged += __handler; + return 0; + } + catch (global::System.Exception __ex) + { + return __ex.HResult; + } + } + +#if !NETSTANDARD2_0 + [UnmanagedCallersOnly] +#endif + private static unsafe int Do_Abi_remove_ErrorsChanged_2(IntPtr thisPtr, global::WinRT.EventRegistrationToken token) + { + try + { + var __this = global::WinRT.ComWrappersSupport.FindObject(thisPtr); + if (_ErrorsChanged_TokenTables.TryGetValue(__this, out var __table) && __table.RemoveEventHandler(token, out var __handler)) + { + __this.ErrorsChanged -= __handler; + } + return 0; + } + catch (global::System.Exception __ex) + { + return __ex.HResult; + } + } + } + internal static ObjectReference FromAbi(IntPtr thisPtr) => ObjectReference.FromAbi(thisPtr); + + public static implicit operator INotifyDataErrorInfo(IObjectReference obj) => (obj != null) ? new INotifyDataErrorInfo(obj) : null; + protected readonly ObjectReference _obj; + public IObjectReference ObjRef { get => _obj; } + public IntPtr ThisPtr => _obj.ThisPtr; + public ObjectReference AsInterface() => _obj.As(); + public A As() => _obj.AsType(); + public INotifyDataErrorInfo(IObjectReference obj) : this(obj.As()) { } + internal INotifyDataErrorInfo(ObjectReference obj) + { + _obj = obj; + + _ErrorsChanged = + new EventSource>(_obj, + _obj.Vftbl.add_ErrorsChanged_1, + _obj.Vftbl.remove_ErrorsChanged_2); + } + + public unsafe global::System.Collections.IEnumerable GetErrors(string propertyName) + { + MarshalString __propertyName = default; + IntPtr __retval = default; + try + { + __propertyName = MarshalString.CreateMarshaler(propertyName); + global::WinRT.ExceptionHelpers.ThrowExceptionForHR(_obj.Vftbl.GetErrors_3(ThisPtr, MarshalString.GetAbi(__propertyName), out __retval)); + return global::ABI.System.Collections.Generic.IEnumerable.FromAbi(__retval); + } + finally + { + MarshalString.DisposeMarshaler(__propertyName); + global::ABI.System.Collections.Generic.IEnumerable.DisposeAbi(__retval); + } + } + + public unsafe bool HasErrors + { + get + { + byte __retval = default; + global::WinRT.ExceptionHelpers.ThrowExceptionForHR(_obj.Vftbl.get_HasErrors_0(ThisPtr, out __retval)); + return __retval != 0; + } + } + + public event global::System.EventHandler ErrorsChanged + { + add => _ErrorsChanged.Subscribe(value); + remove => _ErrorsChanged.Unsubscribe(value); + } + + private EventSource> _ErrorsChanged; + } + + internal static class INotifyDataErrorInfo_Delegates + { + public unsafe delegate int get_HasErrors_0(IntPtr thisPtr, byte* value); + public unsafe delegate int add_ErrorsChanged_1(IntPtr thisPtr, IntPtr handler, global::WinRT.EventRegistrationToken* token); + public unsafe delegate int remove_ErrorsChanged_2(IntPtr thisPtr, global::WinRT.EventRegistrationToken token); + public unsafe delegate int GetErrors_3(IntPtr thisPtr, IntPtr propertyName, IntPtr* result); + } +} diff --git a/cswinrt/code_writers.h b/cswinrt/code_writers.h index fec695657..c07a14cae 100644 --- a/cswinrt/code_writers.h +++ b/cswinrt/code_writers.h @@ -1501,6 +1501,28 @@ public void Dispose() => %.Dispose(); target); } + void write_notify_data_error_info_members(writer& w) + { + w.write(R"( +public global::System.Collections.IEnumerable GetErrors(string propertyName) => AsInternal(new InterfaceTag()).GetErrors(propertyName); + +global::System.Collections.IEnumerable global::System.ComponentModel.INotifyDataErrorInfo.GetErrors(string propertyName) => GetErrors(propertyName); +public event global::System.EventHandler ErrorsChanged +{ +add => AsInternal(new InterfaceTag()).ErrorsChanged += value; +remove => AsInternal(new InterfaceTag()).ErrorsChanged -= value; +} + +event global::System.EventHandler global::System.ComponentModel.INotifyDataErrorInfo.ErrorsChanged +{ +add => this.ErrorsChanged += value; +remove => this.ErrorsChanged -= value; +} +public bool HasErrors => AsInternal(new InterfaceTag()).HasErrors; +bool global::System.ComponentModel.INotifyDataErrorInfo.HasErrors {get => HasErrors; } +)"); + } + void write_custom_mapped_type_members(writer& w, std::string_view target, mapped_type const& mapping) { if (mapping.abi_name == "IIterable`1") @@ -1527,11 +1549,11 @@ target); { write_list_members(w, target, false); } - else if (mapping.abi_name == "IBindableIterable") + else if (mapping.mapped_namespace == "System.Collections" && mapping.mapped_name == "IEnumerable") { write_nongeneric_enumerable_members(w, target); } - else if (mapping.abi_name == "IBindableVector") + else if (mapping.mapped_namespace == "System.Collections" && mapping.mapped_name == "IList") { write_nongeneric_list_members(w, target, false); } @@ -1539,6 +1561,10 @@ target); { write_idisposable_members(w, target); } + else if (mapping.mapped_namespace == "System.ComponentModel" && mapping.mapped_name == "INotifyDataErrorInfo") + { + write_notify_data_error_info_members(w); + } } std::pair find_property_interface(writer& w, TypeDef const& setter_iface, std::string_view prop_name) diff --git a/cswinrt/helpers.h b/cswinrt/helpers.h index b4e0a7a24..d392daacb 100644 --- a/cswinrt/helpers.h +++ b/cswinrt/helpers.h @@ -462,6 +462,8 @@ namespace cswinrt }, { "Microsoft.UI.Xaml.Data", { + { "DataErrorsChangedEventArgs", "System.ComponentModel", "DataErrorsChangedEventArgs" }, + { "INotifyDataErrorInfo", "System.ComponentModel", "INotifyDataErrorInfo", true, true }, { "INotifyPropertyChanged", "System.ComponentModel", "INotifyPropertyChanged" }, { "PropertyChangedEventArgs", "System.ComponentModel", "PropertyChangedEventArgs" }, { "PropertyChangedEventHandler", "System.ComponentModel", "PropertyChangedEventHandler" },