XAML relative binding trick

Corrado Cavalli
Corrado Cavalli
Published in
2 min readJan 26, 2016

MVVM newcomers find creating a UI like this (a simple ListView containing a button that removes current row) quite intricated.

image

This because, while you can add a command to the item bound to each row, it’s more convenient to have a common DeleteCommand on parent ViewModel that accepts the Item to remove from the collection feeding the list.

Here’s our ViewModel:

public class MyViewModel
{
private RelayCommand<ReportUnit> deleteCommand;
public MyViewModel()
{
this.Items = new ObservableCollection<ReportUnit>();
for (int i = 0; i < 10; i++)
{
this.Items.Add(new ReportUnit() { Name = $"Item {i}" });
}
}
public RelayCommand<ReportUnit> DeleteCommand
{
get
{
return this.deleteCommand
?? (this.deleteCommand = new RelayCommand<ReportUnit>((o) =>
{
this.Items.Remove(o);
}));
}
}
public ObservableCollection<ReportUnit> Items { get; private set; }
}
public class ReportUnit
{
public string Name { get; set; }
}

And here’s the page XAML:

<Page x:Class="DemoBinding.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Page.Resources>
<Style x:Key="ListItemContainerStyle"
TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
</Style>

</Page.Resources>
<Grid x:Name="RootGrid">
<ListView ItemsSource="{Binding Items}"
ItemTemplate="{StaticResource MyItemTemplate}"
ItemContainerStyle="{StaticResource ListItemContainerStyle}">

</ListView>
</Grid>
</Page>

The “magic” is of course inside MyItemTemplate:

<DataTemplate x:Key="MyItemTemplate">
<Grid d:DesignWidth="568.775" Height="80"
d:DesignHeight="100">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="100" />
</Grid.ColumnDefinitions>
<TextBlock TextWrapping="Wrap"
Text="{Binding Name}"
VerticalAlignment="Center"
FontSize="26.667" />
<Button Grid.Column="1"
Content="Delete"
HorizontalAlignment="Stretch"
Command="{Binding DataContext.DeleteCommand, ElementName=RootGrid}"
CommandParameter="{Binding}"
VerticalAlignment="Stretch"
Margin="5" />

</Grid>
</DataTemplate>

As you see, the button ‘steal’ the DataContext of RootGrid element and invokes MyViewModel’s DeleteCommand while passing its own DataContext as CommandParameter.

Simple and clean.

Smile

--

--

Corrado Cavalli
Corrado Cavalli

Senior Sofware Engineer at Microsoft, former Xamarin/Microsoft MVP mad about technology. MTB & Ski mountaineering addicted.