0

In order to make a WPF project more clear, I decided to define the layout of the rows of an ItemsControl in an external UserControl.

This is the main page showing the list:

<ScrollViewer Name="ItemsScroll" Grid.Row="1" VerticalScrollBarVisibility="Auto">
    <ItemsControl Name="ItemsList">
        <ItemsControl.Resources>
            <DataTemplate DataType="{x:Type local:OptionSetItem}">
                <local.controls:OptionItemControl />
            </DataTemplate>
        </ItemsControl.Resources>
    </ItemsControl>
</ScrollViewer>

local.controls:OptionItemControl is defined in another file:

<UserControl x:Class="OptionSetManager.Controls.OptionItemControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="100" d:DesignWidth="300">

    <Grid Height="30">
        <Grid.Resources>
            <BooleanToVisibilityConverter x:Key="BoolToVis" />
        </Grid.Resources>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="2*" />
            <ColumnDefinition Width="7*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>

        <TextBlock Name="ItemId" Grid.Column="0" VerticalAlignment="Center" TextAlignment="Center" FontSize="16" Foreground="DarkGray" Text="{Binding Id}" />
        <TextBox Name="ItemText" Grid.Column="1" VerticalContentAlignment="Center" FontSize="16" Text="{Binding Text}" BorderBrush="{x:Null}" Background="#FFF0F0F0" IsReadOnly="{Binding ToBeDeleted}" HorizontalAlignment="Right" Width="210" />
        <Button Name="DeleteExistingButton" Grid.Column="2" Click="DeleteExistingButton_Click" Tag="{Binding Id}" Cursor="Hand" ToolTip="Mark as deleted">
            <Button.Template>
                <ControlTemplate>
                    <Image Source="/Assets/delete.png"/>
                </ControlTemplate>
            </Button.Template>
        </Button>

        <Rectangle Fill="Red" Height="3" Margin="15,0" Grid.Column="0" Visibility="{Binding ToBeDeleted, Converter={StaticResource BoolToVis}}"></Rectangle>

    </Grid>
</UserControl>

As you can see, the custom control contains a DeleteExistingButton that fires a Click event. The goal is to catch this event from the main page where the list is.

I followed some answers like this but I'm stuck at a certain point I'll show you later. First, this is the code behind the UserControl:

namespace OptionSetManager.Controls
{
    public partial class OptionItemControl : UserControl
    {
        public event EventHandler OnDeleteExistingButtonClick;

        public OptionItemControl()
        {
            InitializeComponent();
        }

        private void DeleteExistingButton_Click(object sender, RoutedEventArgs e)
        {
            if (this.OnDeleteExistingButtonClick != null) OnDeleteExistingButtonClick(this, e);
        }
    }
}

Here I'm propagating the event to an handler, if exists. I should attach it from the main page, but obviously I can't do something like

OptionItemControl.OnDeleteExistingButtonClick += new EventHandler(UserControl_ButtonClick);

because OptionItemControl is not an instance of an object, but just an element in the DataTemplate.

What am I missing?

Community
  • 1
  • 1
TheUnexpected
  • 3,077
  • 6
  • 32
  • 62

1 Answers1

0

You can handle your OnDeleteExistingButtonClick event in your DataTemplate with the following syntax:

<DataTemplate DataType="{x:Type local:OptionSetItem}">
    <local.controls:OptionItemControl OnDeleteExistingButtonClick="YourHandler"/>
</DataTemplate>

Note: You should name your event DeleteExistingButtonClick instead of OnDeleteExistingButtonClick (it's a convention, the function that raise the event should be named OnYourEvent or RaiseYourEvent)

nkoniishvt
  • 2,442
  • 1
  • 14
  • 29