How to make a mode of related sources find the ancestor (or equivalent) in UWP

I am trying to do something that seems to be very simple (at least in WPF). I have a list page and a datatemplate, now that the datatemplate calls the user control with a button in it. Nothing unusual, but the button command is not part of the listbox source, and I cannot find an easy way to tell the button where to look for the command. Here is the script

<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> 

Note that this does not compile, as in UWP there is no ancestor search mode? How can I do this, I continue to look at Google, but can not find anything about it.

thanks

+6
source share
2 answers

The answer is a dependency property. I had the same problem. First, if you do not have a DataTemplate, the solution is straightforward:

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

You set the DataContext UserControl in your constructor by your code.

If you are planning your team for us inside a DataTemplate, you will need DependecyProperty.

Example:

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

And to back it up, you create a dependency property for this command:

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

So, now when you use your custom control, it will have the MyCommand property on it, which you can bind to any command from the ViewModel if the template parent matches the one you provided, and also the parameter is bound to the actual element that the control is part.

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

A simple example:

UserControl Code for

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

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> 

Usage in Page.xaml:

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

In Windows 10 UWP, there is a concept called x:Bind . In x:Bind code behind becomes the datacontext for binding. Therefore, if you add a property to the user control code behind, pointing to a view model that can be used to bind the command.

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

In XAML -

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

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

  OR 

You can use ElementName with traditional binding to achieve the result.

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

Refer - Unable to access parent datacontext

Update:. To access the delete command from the datacontext page, you can use the following method, assuming that changing the usercontrol datacontext (from the client) to the datacontext page does not affect anything else inside the usercontrol.

 <DataTemplate x:Key="MyDataTemplate"> <local:MyButton DataContext="{Binding DataContext, ElementName = PageName}" /> </DataTemplate> <Button Command="{Binding DeleteCommand}" Content="Delete" /> 
+2
source

All Articles