Windows runtime 将操作绑定到XAML中UserControl的属性

Windows runtime 将操作绑定到XAML中UserControl的属性,windows-runtime,winrt-xaml,Windows Runtime,Winrt Xaml,我有一个用户控件,它有一个按钮和按钮要执行的操作的依赖属性。包含控件的页面在XAML中设置操作 MyUserControl.cs 按钮和类型为操作的依赖属性按钮操作。单击按钮时,它将执行按钮操作 MainPage.xaml.cs 行动1 行动2 MainPage.xaml 使用ButtonAction=Action1显示MyUserControl的实例 问题:ButtonAction属性不是从XAML分配的 MyUserControl.cs MyUserControl.xaml MainPage

我有一个用户控件,它有一个按钮和按钮要执行的操作的依赖属性。包含控件的页面在XAML中设置操作

MyUserControl.cs

按钮和类型为
操作
的依赖属性
按钮操作
。单击按钮时,它将执行
按钮操作

MainPage.xaml.cs

行动1

行动2

MainPage.xaml

使用ButtonAction=Action1显示MyUserControl的实例

问题:ButtonAction属性不是从XAML分配的

MyUserControl.cs

MyUserControl.xaml

MainPage.xaml


在这种情况下,还将调用用户控件中的PropertyChanged回调。(此处理程序仅用于诊断目的。我不知道如何在实践中使用它来支持属性)。

问题在于数据绑定。
ButtonAction=“{Binding Action1}”
中的
Action1
应该是公共属性,而您将其定义为私有变量

此外,您不能像那样直接在代码隐藏中声明普通属性。您将需要依赖属性,或者更常见的是,在实现
INotifyPropertyChanged
的viewmodel中需要公共属性

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));
        }
    }
}
如果使用第二种方法,我们将需要创建一个viewmodel类,如下所示,并带有
Action1
属性。请注意,
OnPropertyChanged
内容只是实现
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));
        }
    }
}
然后您只需要将其分配到主页的
DataContext

    public MainPage()
    {
        this.InitializeComponent();

        var vm = new ViewModel();
        vm.Action1 = (() =>
        {
            Debug.WriteLine("Action1 called");
        });

        this.DataContext = vm;
    }

通过这两项更改,您的
按钮操作
回调现在应该启动了。:)

主页上的数据上下文是什么?如果它不是页面,那么您必须设置ButtonAction=“{Binding Action1,ElementName=x:name of the MainPage}”MainPage没有数据上下文-但是当在代码中分配操作时,它可以正常工作。我尝试了你的建议(设置页面名称和ElementName),结果没有什么不同。不过还是要谢谢你。这两种解决方案都证实有效。非常有趣的是,INotifyPropertyChanged和DependencyObject在xaml中的数据绑定工作是等效的。DependencyObject解决方案的代码是:“类ViewModel:DependencyObject{public Action Action1{get{return(Action)GetValue(Action1Property);}set{SetValue(Action1Property,value);}”public static readonly dependencProperty Action1Property=dependencProperty.Register(“Action1”、typeof(Action)、typeof(ViewModel)、newpropertyMetadata(null));}`这是正确的。您可能已经知道,如果使用dp,则需要通过向绑定表达式添加
ElementName=MyMainPage
来稍微修改xaml。比如
ButtonAction=“{Binding Action1,ElementName=MyMainPage}”
我明白了。我认为不应该在vm中定义依赖属性。此外,vm不应该实现DependencyObject。在当前上下文中,应该在MyMainPage.xaml.cst中定义dp Action1,这是一个改进!谢谢在dp解决方案中,我删除了类
ViewModel
,将
Action1
依赖属性移动到MainPage.xaml.cs中,并将xaml更改为
ButtonAction=“{Binding Action1,ElementName=MyMainPage}
    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <local:MyUserControl x:Name="myUserControl" ButtonAction="{Binding Action1}"/>
</Grid>
        private void Page_Loaded(object sender, RoutedEventArgs e) {
        this.myUserControl.ButtonAction = Action1;
    }
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));
        }
    }
}
    public MainPage()
    {
        this.InitializeComponent();

        var vm = new ViewModel();
        vm.Action1 = (() =>
        {
            Debug.WriteLine("Action1 called");
        });

        this.DataContext = vm;
    }