Corrado's Blog 2.0

Online thoughts of a technology funatic

XAML relative binding trick

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

No Responses to “XAML relative binding trick”

RSS feed for comments on this post. TrackBack URL

Leave a Response