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).
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. :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With