Xaml 如何在UWP中使用相对资源模式查找祖先(或等价物)

Xaml 如何在UWP中使用相对资源模式查找祖先(或等价物),xaml,uwp,Xaml,Uwp,我正在尝试做一些人们认为应该非常简单的事情(至少在WPF中是这样)。 我有一个带有列表框和datatemplate的页面,现在datatemplate调用了一个带有按钮的用户控件。没什么特别的,但是buttons命令不是listboxsource的一部分,我找不到一个简单的方法告诉按钮在哪里可以找到该命令。下面是一个场景 <Page x:Class="App1.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/p

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

<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中没有模式查找祖先?我该怎么做呢?我一直在看谷歌,但找不到任何关于它的信息


谢谢

在Windows10UWP中有一个叫做
x:Bind
的概念。在
x:Bind
中,代码隐藏成为绑定的数据上下文。因此,如果在用户控件的代码隐藏中添加指向视图模型的属性,该属性可用于绑定命令

public class MyButton
{
   public ViewModel ButtonViewModel 
   { 
      get
      { 
          return ButtonViewModelObject;
      }
   }
}    
在XAML中-

<Button Command="{x:Bind ButtonViewModel.DeleteCommand}" Content="Delete" />
您可以将ElementName与传统绑定一起使用以实现此结果

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

参考-

更新:若要从页面的datacontext访问delete命令,可以使用以下方法,前提是-将usercontrol的datacontext(从customer)更改为页面的datacontext不会影响usercontrol中的任何其他内容

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

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

答案是依赖属性。我也有同样的问题。 首先,如果没有涉及数据模板,则解决方案是直接的:

(this.Content as FrameworkElement).DataContext = this;
将UserControl构造函数中的DataContext设置为其代码隐藏

如果您计划在DataTemplate中使用您的命令,那么您也需要DependecProperty

例如:

 <DataTemplate>
     <Button Command="{Binding DataContext.MyCommand, ElementName=ParentName}">
 </DataTemplate>
因此,现在当您使用用户控件时,将有一个MyCommand属性,您可以绑定到ViewModel中的任何命令,只要模板父级与您提供的模板父级匹配,并且参数绑定到控件所属的实际项

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

简单的例子:

用户控制代码隐藏

 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>()));



}
公共密封部分类ListviewUserControl:UserControl
{
公共ListviewUserControl()
{
this.InitializeComponent();
(this.Content作为FrameworkElement)。DataContext=this;
}
公用ICommand按钮命令
{
获取{return(ICommand)GetValue(ButtonCommandProperty);}
set{SetValue(ButtonCommandProperty,value);}
}
//使用DependencyProperty作为ButtonCommand的后备存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性ButtonCommandProperty=
Register(“ButtonCommand”、typeof(ICommand)、typeof(ListviewUserControl)、newpropertyMetadata(null));
公共可观察收集项目来源
{
get{return(ObservableCollection)GetValue(ItemsSourceProperty);}
set{SetValue(ItemsSourceProperty,value);}
}
//使用DependencyProperty作为ItemsSource的备份存储。这将启用动画、样式、绑定等。。。
公共静态只读依赖项Property ItemsSourceProperty=
DependencyProperty.Register(“ItemsSource”、typeof(ObservableCollection)、typeof(ListviewUserControl)、new PropertyMetadata(new ObservableCollection());
}
UserControl 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}"/>


谢谢您的回答,但这对我来说不是一个好的解决方案,因为我将该按钮放在一个单独的用户控件中,以便在许多地方重复使用它。因此,ViewModel在不同的屏幕上会有所不同。如果允许相对源忽略它是哪个viewmodel,它只需查看父对象的datacontext即可。我尝试了ElementName,但在这种情况下它不起作用,它找不到调用页的名称。@adminSoftDK:是否类似于-您在datatemplate内的usercontrol中有按钮,并且delete命令位于页面的datacontext中,其中有
列表框
?是的,deletecommand位于页面的datacontext中,但是datatemplate当前的datacontext是针对每个客户的。我可能应该做一个更好的示例,我也尝试过这个。这就快到了,但我还将当前项的Id作为命令参数传递。它们属于原始datacontext,所以按照您刚才所说的操作,将找到该命令,但现在我对命令参数有了相同的操作。感谢您的帮助:)我没有得到usercontrols中绑定需要的最后一部分:button,button command={binding MyCommand}没有任何功能,按钮必须查看模板化的父级或其他内容才能找到依赖项属性?依赖项属性始终位于usercontrols代码后面。它只允许在用户控件中的对象和控件外部的对象之间进行绑定。有时,我将整个ListView放入用户控件中,并为ItemSource创建一个依赖属性,这样我就可以在不同的视图中重用整个列表,我只需绑定ItemSource和不同的命令及其标签,如果它们发生更改,我看到了,这很有意义,我稍后会测试:)非常感谢:)不用担心,我很高兴它能帮助。。。首先有点让人困惑,但一旦你明白了…我在使用附加属性和相对资源自绑定方面分享了一个解决方案
<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>
<Controls:ListviewUserControl ItemsSource="{Binding ViewModelsItemsList}" ButtonCommand="{Binding ViewModelsCommand}"/>