What properties/functions/anything must go in the IDLs that I write for custom XAML controls written in C /WinRT?
Example
When I create a custom C /WinRT XAML control in Visual Studio, it creates 4 files:
- MyControl.xaml
- MyControl.idl
- MyControl.h
- MyControl.cpp
The IDL file is basic and includes a simple property:
namespace MyNamespace
{
[default_interface]
runtimeclass MyControl : Windows.UI.Xaml.Controls.UserControl
{
MyControl();
Int32 MyProperty;
}
}
Interestingly, the .h
file also includes another function in addition to this property:
#pragma once
#include "winrt/Windows.UI.Xaml.h"
#include "winrt/Windows.UI.Xaml.Markup.h"
#include "winrt/Windows.UI.Xaml.Interop.h"
#include "winrt/Windows.UI.Xaml.Controls.Primitives.h"
#include "MyControl.g.h"
namespace winrt::MyNamespace::implementation
{
struct MyControl : MyControlT<MyControl>
{
MyControl();
int32_t MyProperty();
void MyProperty(int32_t value);
void ClickHandler(Windows::Foundation::IInspectable const& sender, Windows::UI::Xaml::RoutedEventArgs const& args);
};
}
namespace winrt::MyNamespace::factory_implementation
{
struct MyControl : MyControlT<MyControl, implementation::MyControl>
{
};
}
Which the .xaml
has no problem binding to:
<!-- ... -->
<Button x:Name="Button" Click="ClickHandler">Click Me</Button>
<!-- ... -->
Question
It's not clear to me when I need to introduce a function or property on my IDL in order to consume it in XAML.
Do all properties need to be added to the IDL? Just dependency properties? Do functions ever have to appear in the IDL?
Why does MyProperty
appear in the IDL, but not ClickHandler
?
Thanks!
CodePudding user response:
Short answer:
Needs to be in IDL? | Needs to be implemented in C ? | ||
---|---|---|---|
Property | x:Bind |
✅ Yes, the property must be exposed in the IDL. | ✅ Yes, you must implement the property. |
Binding |
❌ No, but your control must implement ICustomPropertyProvider and ICustomProperty . See Using the {Binding} markup extension with C /WinRT. |
(You must implement those interfaces, so yes) | |
Function | Delegate | ❌ No, the function simply needs to be public in your implementation. | ✅ Yes, by definition you must implement the function you want to call. |
x:Bind |
✅ Yes, the function must be exposed in the IDL. | ✅ Yes, by definition you must implement the function you want to call. | |
Element | x:Bind |
✅ Yes, the element must be exposed in the IDL. | ❌ No, the implementation code will be auto-generated; don't write any C . |
Or another way of putting it:
Anything using
x:Bind
needs to be in the IDL.- This includes everything with
x:Bind
---properties and functions are obvious, but also elements (see Element-to-element binding). So if you want tox:Bind
theContent
of aTextBlock
to theText
of aTextBox
, you'll need to expose theTextBox
in the IDL.
- This includes everything with
Everything else does not need to be in the IDL.
To use old-school (and less efficient & more brittle)
Binding
, your control must implementICustomPropertyProvider
andICustomProperty
. See Using the {Binding} markup extension with C /WinRT.If you reference a function as a delegate (e.g.
PointerMoved="MyTextBlock_PointerMovedHandler"
), the function simply needs to be a public method in your control's class.
MSDN's XAML controls; bind to a C /WinRT property provides the full answer:
All entities consumed by using the XAML {x:Bind} markup extension must be exposed publicly in IDL. Furthermore, if XAML markup contains a reference to another element that's also in markup, then the getter for that markup must be present in IDL.
<Page x:Name="MyPage"> <StackPanel> <CheckBox x:Name="UseCustomColorCheckBox" Content="Use custom color" Click="UseCustomColorCheckBox_Click" /> <Button x:Name="ChangeColorButton" Content="Change color" Click="{x:Bind ChangeColorButton_OnClick}" IsEnabled="{x:Bind UseCustomColorCheckBox.IsChecked.Value, Mode=OneWay}"/> </StackPanel> </Page>
The ChangeColorButton element refers to the UseCustomColorCheckBox element via binding. So the IDL for this page must declare a read-only property named UseCustomColorCheckBox in order for it to be accessible to binding.
The click event handler delegate for UseCustomColorCheckBox uses classic XAML delegate syntax, so that doesn't need an entry in the IDL; it just needs to be public in your implementation class. On the other hand, ChangeColorButton also has an {x:Bind} click event handler, which must also go into the IDL.
runtimeclass MyPage : Windows.UI.Xaml.Controls.Page { MyPage(); // These members are consumed by binding. void ChangeColorButton_OnClick(); Windows.UI.Xaml.Controls.CheckBox UseCustomColorCheckBox{ get; }; }
You don't need to provide an implementation for the UseCustomColorCheckBox property. The XAML code generator does that for you.