Tutorial: how to access click events from UserControls in xaml and C# WPF

CB 46 Reputation points
2021-07-26T13:56:32.25+00:00

I need some basic instruction regarding a custom User Control. In a New WPF C# .net app in visual studio, I added a New UserControl, UserControl1.
In it I added two buttons, Button1 and Button2. I added the control to the main window.

What code is needed to be able to define the click events of either button in xaml in the main window so they fire in the code behind?

User Control Code

<UserControl x:Class="test.UserControl1"
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"
xmlns:local="clr-namespace:test"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800">
<Grid>
<StackPanel Orientation="Vertical">
<Button x:Name="button1" Content="Button1" Width="75"/>
<Button x:Name="button2" Content="Button2" Width="75"/>
</StackPanel>

</Grid>

</UserControl>

Main Window Xaml

<Grid>
    <local:UserControl1>
     <!-- something like b1_Click = ClickB1 ??-->
        <!-- something like b2_Click = ClickB2 ??-->
    </local:UserControl1>
</Grid>

Code Behind Main Window

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
    }

    private void ClickB1(object sender, RoutedEventArgs e)
    {
        Debug.WriteLine((sender as Button).Name);
    }
    private void ClickB2(object sender, RoutedEventArgs e)
    {
        Debug.WriteLine((sender as Button).Name);
    }
}
Developer technologies Windows Presentation Foundation
0 comments No comments
{count} votes

4 answers

Sort by: Most helpful
  1. CB 46 Reputation points
    2021-07-26T15:58:45.147+00:00

    Well I don't know what you mean by that exactly. I've been trying various samples that seem related.. this is what I have now, and the two button events fire. Not sure now to get the calling element, also, they dont fire if I subscribe to the events in MainWindow XAML, only if I do it in code behind. Sorry format looks strange. I have no idea how the formatting controls on this blog work whatsoever. Nothing is obvious and nothing works by default.

    UserControl
        <StackPanel Orientation="Vertical">
            <Button x:Name="button1"  Content="Button1" Width="75" Click="button1_Click"/>
            <Button x:Name="button2" Content="Button2" Width="75" Click="button2_Click"/>
        </StackPanel>
    

    UC code:

        public static readonly RoutedEvent ClickB1Event = EventManager.RegisterRoutedEvent(
    

    "ClickB1", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(UserControl1));

        public static readonly RoutedEvent ClickB2Event = EventManager.RegisterRoutedEvent(
    

    "ClickB2", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(UserControl1));

        public event RoutedEventHandler ClickB1;
        public event RoutedEventHandler ClickB2;
    
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            if (ClickB1 != null)
            {
                ClickB1(this, e);
            }
        }
        private void button2_Click(object sender, RoutedEventArgs e)
        {
            if (ClickB2 != null)
            {
                ClickB2(this, e);
            }
        }
    

    MainWindow xaml

     <local:UserControl1 x:Name="ctrl1" ClickB1="Click1" ClickB2="Click2"/>
    

    MainWindow code:

    public MainWindow()
    {
    InitializeComponent();

            ctrl1.ClickB1 += Click1;
            ctrl1.ClickB2 += Click2;           
        }
    
        private void Click1(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine((sender as UserControl1).Name);
        }
        private void Click2(object sender, RoutedEventArgs e)
        {
            Debug.WriteLine((sender as UserControl1).Name);
        }
    
    1 person found this answer helpful.

  2. Lloyd Sheen 1,486 Reputation points
    2021-07-26T14:32:32.59+00:00

    In your example the Button would be defined as

    <Button Content="Button1" Click="ClickB1"></Button>

    0 comments No comments

  3. Hui Liu-MSFT 48,676 Reputation points Microsoft External Staff
    2021-07-27T05:20:27.367+00:00

    I tested your code and the click event is displayed correctly in Output.
    118181-6.gif
    If you want to display the name of the Button in the message box, you could updated MainWindow code as follows:

    public partial class MainWindow : Window  
      {  
        public MainWindow()  
        {  
          InitializeComponent();  
          ctrl1.ClickB1 += Click1;  
          ctrl1.ClickB2 += Click2;  
        }  
        private void Click1(object sender, RoutedEventArgs e)  
        {  
          MessageBox.Show((sender as UserControl1).Name);  
        }  
        private void Click2(object sender, RoutedEventArgs e)  
        {  
          MessageBox.Show((sender as UserControl1).Name);  
        }  
      }  
    

    The result is shown in the figure:
    118116-4.gif
    Here is a simple example of using UserControl with Button click event. The purpose of UserControl is to combine a set of controls into a reusable component. After you set the required controls and events in UserControl, you could directly use UserControl and its events in wpf. You can also refer to the example of UserControl Class .
    The code of UserControl.xaml is as follows:

    <StackPanel >  
            <Button x:Name="button1"  Content="Button1" Width="75" Click="button1_Click"/>  
            <Button x:Name="button2" Content="Button2" Width="75" Click="button2_Click"/>  
        </StackPanel>  
    

    The code of UserControl1.xaml.cs is as follows:

    private void button1_Click(object sender, RoutedEventArgs e)  
        {  
          Button clickedButton = sender as Button;  
          MessageBox.Show(clickedButton.Name);  
            
        }  
        private void button2_Click(object sender, RoutedEventArgs e)  
        {  
          MessageBox.Show("button2 clicked");  
        }  
    

    The code of MainWindow.xaml is as follows:

     <Grid>  
            <local:UserControl1 Width="100" Height="100"  Background="AliceBlue"/>  
        </Grid>  
    

    The result is shown in the figure:
    118134-5.gif

    0 comments No comments

  4. Emon Haque 3,176 Reputation points
    2021-07-27T10:37:28.277+00:00

    If you want to handle those events anywhere other than the UserControl1, you've to call RaiseEvent in the EventHandler of those buttons in UserControl1. Here you can learn more about these. In the UserControl1.xaml have these:

    <UserControl x:Class="WPFTest.UserControl1" ...>  
        <StackPanel Orientation="Vertical">  
            <Button x:Name="button1" Content="Button1" Width="75" Click="button1_Click"/>  
            <Button x:Name="button2" Content="Button2" Width="75" Click="button2_Click"/>  
        </StackPanel>  
    </UserControl>  
    

    in code behind of the UserControl1.xaml.cs have these:

    public partial class UserControl1 : UserControl  
    {  
        public static readonly RoutedEvent ClickB1Event = EventManager.RegisterRoutedEvent(  
            "ClickB1", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(UserControl1));  
        public static readonly RoutedEvent ClickB2Event = EventManager.RegisterRoutedEvent(  
            "ClickB2", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(UserControl1));  
        public event RoutedEventHandler ClickB1 {  
            add { AddHandler(ClickB1Event, value); }  
            remove { RemoveHandler(ClickB1Event, value); }  
        }  
        public event RoutedEventHandler ClickB2 {  
            add { AddHandler(ClickB2Event, value); }  
            remove { RemoveHandler(ClickB2Event, value); }  
        }  
        public UserControl1() => InitializeComponent();  
        void button1_Click(object sender, RoutedEventArgs e) => RaiseEvent(new RoutedEventArgs(ClickB1Event));  
        void button2_Click(object sender, RoutedEventArgs e) => RaiseEvent(new RoutedEventArgs(ClickB2Event));  
    }  
    

    With these in UserControl1 if you do this in MainWindow.xaml:

    <Window x:Class="WPFTest.MainWindow" ...>  
        <Grid>  
            <local:UserControl1 ClickB1="UserControl1_ClickB1"  
                                ClickB2="UserControl1_ClickB2"/>  
        </Grid>  
    </Window>  
    

    and this in MainWindow.xaml.cs:

    public partial class MainWindow : Window  
    {  
        public MainWindow() => InitializeComponent();  
        void UserControl1_ClickB1(object sender, RoutedEventArgs e) => Debug.WriteLine("B1");  
        void UserControl1_ClickB2(object sender, RoutedEventArgs e) => Debug.WriteLine("B2");  
    }  
    

    it'll work.

    0 comments No comments

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.