Bind an Action to a property of a UserControl in XAML
windows-runtime, winrt-xaml
Solution
The issue is in your data binding. The `Action1` in `ButtonAction="{Binding Action1}"` should be a public property while you defined it as a private variable.
Also, you cannot just declare a normal property directly in the code behind like that. You will need either a dependency property, or more commonly, a public property inside a viewmodel which implements `INotifyPropertyChanged`.
If we go with the second approach, we will need to create a viewmodel class like the following with an `Action1` property. Note the `OnPropertyChanged` stuff is just the standard way of implementing `INotifyPropertyChanged`.
public class ViewModel : INotifyPropertyChanged
{
private Action _action1;
public Action Action1
{
get { return _action1; }
set
{
_action1 = value;
OnPropertyChanged("Action1");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}
And then you just need to assign this to the `DataContext` of your main page.
public MainPage()
{
this.InitializeComponent();
var vm = new ViewModel();
vm.Action1 = (() =>
{
Debug.WriteLine("Action1 called");
});
this.DataContext = vm;
}
With these two changes, your `ButtonAction` callback should be firing now. :)
Problem
I have a user control which has a button and a dependency property for the action the button is to execute. The page which contains the control sets the action in XAML. MyUserControl.cs A Button, and dependency property `ButtonAction`, of type `Action`. When the button is clicked it executes the `ButtonAction`. MainPage.xaml.cs Action Action1 Action Action2 MainPage.xaml Present an instance of `MyUserControl`, with ButtonAction=Action1 The problem: The ButtonAction property is not assigned from the XAML MyUserControl.cs ``` public sealed partial class MyUserControl : UserControl { public Action ButtonAction { get { return (Action)GetValue(ButtonActionProperty); } set { SetValue(ButtonActionProperty, value); } } public static readonly DependencyProperty ButtonActionProperty = DependencyProperty.Register("ButtonAction", typeof(Action), typeof(MyUserControl), new PropertyMetadata(null,ButtonAction_PropertyChanged)); private static void ButtonAction_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { Debug.WriteLine("ButtonAction_PropertyChanged"); // Is not called! } public MyUserControl() { this.InitializeComponent(); } private void Button_Click(object sender, RoutedEventArgs e) { if (ButtonAction != null) { // Never reaches here! ButtonAction(); } } } ``` MyUserControl.xaml ``` <Grid> <Button Click="Button_Click">Do The Attached Action!</Button> </Grid> ``` MainPage.xaml.cs ``` Action Action1 = ( () => { Debug.WriteLine("Action1 called"); }); Action Action2 = (() => { Debug.WriteLine("Action2 called"); }); ``` MainPage.xaml ``` <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <local:MyUserControl x:Name="myUserControl" ButtonAction="{Binding Action1}"/> </Grid> ``` It does work if in the code-behind for MainPage (`MainPage.xaml.cs`) I assign the action in the `Loaded` event. ``` private void Page_Loaded(object sender, RoutedEventArgs e) { this.myUserControl.ButtonAction = Action1; } ``` In this case the PropertyChanged callback in the user control is also called. (This handler is provided only for diagnostic purposes. I can't see how it can be used to support the property in practice).