windows-runtime winrt-xaml

windows runtime - Enlazar una Acción a una propiedad de un UserControl en XAML



windows-runtime winrt-xaml (1)

Tengo un control de usuario que tiene un botón y una propiedad de dependencia para la acción que debe ejecutar el botón. La página que contiene el control establece la acción en XAML.

MyUserControl.cs

Un botón, y la propiedad de dependencia ButtonAction , de tipo Action . Cuando se hace clic en el botón, ejecuta ButtonAction .

MainPage.xaml.cs

Acción Acción1

Acción Acción2

MainPage.xaml

Presente una instancia de MyUserControl , con ButtonAction = Action1

El problema: la propiedad ButtonAction no está asignada desde el 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>

Funciona si en el código subyacente de MainPage ( MainPage.xaml.cs ) asigno la acción en el evento Loaded .

private void Page_Loaded(object sender, RoutedEventArgs e) { this.myUserControl.ButtonAction = Action1; }

En este caso, también se llama a la devolución de llamada PropertyChanged en el control de usuario. (Este controlador solo se proporciona con fines de diagnóstico. No veo cómo se puede usar para respaldar la propiedad en la práctica).


El problema está en su enlace de datos. La Action1 en ButtonAction="{Binding Action1}" debe ser una propiedad pública mientras la define como una variable privada.

Además, no puedes simplemente declarar una propiedad normal directamente en el código de esa manera. Necesitará una propiedad de dependencia o, más comúnmente, una propiedad pública dentro de un modelo de vista que implementa INotifyPropertyChanged .

Si vamos con el segundo enfoque, necesitaremos crear una clase viewmodel como la siguiente con una propiedad Action1 . Tenga en cuenta que el material OnPropertyChanged es solo la forma estándar de implementar 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)); } } }

Y luego solo tiene que asignar esto al DataContext de su página principal.

public MainPage() { this.InitializeComponent(); var vm = new ViewModel(); vm.Action1 = (() => { Debug.WriteLine("Action1 called"); }); this.DataContext = vm; }

Con estos dos cambios, su ButtonAction llamada de ButtonAction debería estar disparando ahora. :)