如何在 UWP 中使用相对源模式查找祖先(或等效项)

How to do relativesource mode find ancestor (or equivalent) in UWP

我正在尝试做一些人们认为应该非常简单的事情(至少在 WPF 中是这样)。 我有一个带有列表框和数据模板的页面,现在数据模板调用了一个带有按钮的用户控件。没什么特别的,但是按钮命令不是列表框源的一部分,我找不到一个简单的方法来告诉按钮在哪里寻找命令。这是场景

<Page x:Class="App1.MainPage"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="using:App1">
<Page.Resources>
    <DataTemplate x:Key="MyDataTemplate">
        <local:MyButton />
    </DataTemplate>
</Page.Resources>
<ListBox ItemTemplate="{StaticResource MyDataTemplate}" ItemsSource="{Binding Customers}" />
</Page>

<UserControl x:Class="App1.MyButton"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

<Button Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=UserControl, AncestorLevel=2}, Path=DataContext.DeleteCommand}" Content="Delete" />
</UserControl>

请注意,这不能编译,因为在 UWP 中没有找到祖先的模式?怎么办啊,我一直在看google,怎么也找不到。

谢谢

在Windows 10 UWP 中有一个叫做x:Bind 的概念。在 x:Bind 中,后面的代码成为绑定的数据上下文。所以如果你在用户控件后面的代码中添加一个属性,指向视图模型,可以用来绑定命令。

public class MyButton
{
   public ViewModel ButtonViewModel 
   { 
      get
      { 
          return ButtonViewModelObject;
      }
   }
}    

在XAML-

<Button Command="{x:Bind ButtonViewModel.DeleteCommand}" Content="Delete" />

参考 - https://msdn.microsoft.com/en-us/library/windows/apps/mt204783.aspx

                                 OR

您可以将 ElementName 与传统绑定结合使用来获得结果。

<Button Command="{Binding DataContext.DeleteCommand, ElementName= UserControlName}" Content="Delete" />

参考 -

更新: 要从页面的数据上下文访问删除命令,可以使用以下方法,假设 - 用户控件的数据上下文(从客户)到页面的数据上下文的更改没有'不会影响用户控件中存在的任何其他内容。

<DataTemplate x:Key="MyDataTemplate">
        <local:MyButton DataContext="{Binding DataContext, ElementName = PageName}" />
 </DataTemplate>

<Button Command="{Binding DeleteCommand}" Content="Delete" />

答案是依赖属性。我有同样的问题。 首先,如果您没有涉及 DataTemplate,则解决方案很简单:

(this.Content as FrameworkElement).DataContext = this;

您在其构造函数中将 UserControl 的 DataContext 设置为其隐藏代码。

如果您计划在 DataTemplate 中使用您的 Command,您也需要 Dependecy属性。

示例:

 <DataTemplate>
     <Button Command="{Binding DataContext.MyCommand, ElementName=ParentName}">
 </DataTemplate>

为了备份它,您为该命令创建了一个依赖项 属性:

 public ICommand MyCommand
    {
        get { return (ICommand)GetValue(MyCommandProperty); }
        set { SetValue(MyCommandProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyCommand.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty MyCommandProperty =
        DependencyProperty.Register("MyCommand", typeof(ICommand), typeof(ownerclass), new PropertyMetadata(0));

所以现在当您使用您的用户控件时,您将拥有一个 MyCommand 属性,您可以绑定到您的 ViewModel 中的任何命令,只要模板父级与您提供的匹配并且参数绑定到控件所属的实际项。

<usercontrols:button MyCommand="{Binding MyCommandFromViewModel}" CommandParameter="{Binding}"/>

简单示例:

背后的UserControl代码

 public sealed partial class ListviewUserControl : UserControl
{
    public ListviewUserControl()
    {
        this.InitializeComponent();

        (this.Content as FrameworkElement).DataContext = this;
    }




    public ICommand ButtonCommand
    {
        get { return (ICommand)GetValue(ButtonCommandProperty); }
        set { SetValue(ButtonCommandProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ButtonCommand.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ButtonCommandProperty =
        DependencyProperty.Register("ButtonCommand", typeof(ICommand), typeof(ListviewUserControl), new PropertyMetadata(null));




    public ObservableCollection<Item> ItemsSource
    {
        get { return (ObservableCollection<Item>)GetValue(ItemsSourceProperty); }
        set { SetValue(ItemsSourceProperty, value); }
    }

    // Using a DependencyProperty as the backing store for ItemsSource.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ItemsSourceProperty =
        DependencyProperty.Register("ItemsSource", typeof(ObservableCollection<Item>), typeof(ListviewUserControl), new PropertyMetadata(new ObservableCollection<Item>()));



}

用户控件Xaml:

<Grid>
    <ListView ItemsSource="{Binding ItemSource}" x:Name="ListView">
        <ListView.ItemTemplate>
            <DataTemplate>
                <!--some item related content-->
                <AppBarButton Icon="Delete" Command="{Binding ButtonCommand, ElementName=ListView}" CommandParameter="{Binding}"/>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
</Grid>

在Page.xaml中的用法:

<Controls:ListviewUserControl ItemsSource="{Binding ViewModelsItemsList}" ButtonCommand="{Binding ViewModelsCommand}"/>