User Controls and Intercommunication
For applications that are composed of multiple user controls, there needs to be coordination and communication between them. For example, an application's MainWindow.xaml
:
<Window x:Class="InterUsrCtrlComm.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:InterUsrCtrlComm" Title="Inter User Control Communication" Height="350" Width="525"> <Grid> <local:ucContent x:Name="content1"/> <local:ucPopupMnu x:Name="popupmnu1"/> </Grid> </Window>
Attach menu event programmatically (in C#):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace InterUsrCtrlComm { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); // Attach menu event handler popupmnu1.MenuItemSelected += new RoutedEventHandler(ucPopupMnu_MenuItemSelected); } /// <summary> /// Event handler for Menu Item Selection in Popup menu. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ucPopupMnu_MenuItemSelected(object sender, RoutedEventArgs e) { // Get menu selection ListBoxItem selection = popupmnu1.SelectedItem; // Take action based on the menu selection content1.SelectedTabItem = selection.Content.ToString(); } } }
If the event is defined with XAML (MainWindows.xaml
), then:
<Window x:Class="InterUsrCtrlComm.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="clr-namespace:InterUsrCtrlComm" Title="Inter User Control Communication" Height="350" Width="525"> <Grid> <local:ucContent x:Name="content1"/> <local:ucPopupMnu x:Name="popupmnu1" MenuItemSelected="ucPopupMnu_MenuItemSelected"/> </Grid> </Window>
The code-behind looks like (MainWindows.xaml.cs
):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace InterUsrCtrlComm { /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); // This next line should not be present, since XAML will add it automatically in InitializeComponent() //popupmnu1.MenuItemSelected += new RoutedEventHandler(ucPopupMnu_MenuItemSelected); } /// <summary> /// Event handler for Menu Item Selection in Popup menu. /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void ucPopupMnu_MenuItemSelected(object sender, RoutedEventArgs e) { // Get menu selection ListBoxItem selection = popupmnu1.SelectedItem; // Take action based on the menu selection content1.SelectedTabItem = selection.Content.ToString(); } } }
It contains 2 user controls:
ucContent
which has the main content for the application.ucPopupMnu
which has a popup menu that triggers events that should affect the content inucContent
.
The MainWindow
coordinates communication between these user controls. ucPopupMnu has routed events that are then intercepted by MainWindow
, and from here trigger some action in ucContent
.
This is how it looks: ucContent
ucContent.xaml
<UserControl x:Class="InterUsrCtrlComm.ucContent" 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="300" d:DesignWidth="600"> <Grid> <TabControl Name="tcMain"> <TabItem Name="tabRed" Header="Red"> <Grid Background="Crimson"></Grid> </TabItem> <TabItem Name="tabGreen" Header="Green"> <Grid Background="DarkGreen"></Grid> </TabItem> <TabItem Name="tabBlue" Header="Blue"> <Grid Background="Navy"></Grid> </TabItem> </TabControl> </Grid> </UserControl>
ucContent.xaml.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace InterUsrCtrlComm { /// <summary> /// Interaction logic for ucContent.xaml /// </summary> public partial class ucContent : UserControl { //----------------------------------------------------------------------------------------- /// <summary> /// Get or set the Selected Tab Item by providing the tab label (string). /// </summary> //----------------------------------------------------------------------------------------- public string SelectedTabItem { get { TabItem tab = (TabItem)tcMain.SelectedItem; return tab.Header.ToString(); } set { switch(value) { case "Red": tcMain.SelectedItem = tabRed; break; case "Green": tcMain.SelectedItem = tabGreen; break; case "Blue": tcMain.SelectedItem = tabBlue; break; } } } //----------------------------------------------------------------------------------------- /// <summary> /// Constructor /// </summary> //----------------------------------------------------------------------------------------- public ucContent() { InitializeComponent(); } } }
ucPopupMnu.xaml
:
<UserControl x:Class="InterUsrCtrlComm.ucPopupMnu" 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="300" d:DesignWidth="200"> <Grid> <ToggleButton IsChecked="{Binding ElementName=popopmnuColorSelection, Path=IsOpen}" Content="Open Popup Menu" Width="130" Height="50" /> <Popup Name="popopmnuColorSelection" Visibility="Visible" Width="150" Placement="Bottom" AllowsTransparency="False" PopupAnimation="Fade" VerticalOffset="-100" HorizontalOffset="100"> <StackPanel> <TextBlock Background="Transparent" Foreground="White" FontWeight="Bold">Select one (double click):</TextBlock> <ListBox Name="lstColors" MouseDoubleClick="lstColors_MouseDoubleClick"> <ListBoxItem>Red</ListBoxItem> <ListBoxItem>Green</ListBoxItem> <ListBoxItem>Blue</ListBoxItem> </ListBox> </StackPanel> </Popup> </Grid> </UserControl>
ucPopupMnu.xaml.cs
:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace InterUsrCtrlComm { /// <summary> /// Interaction logic for ucPopupMnu.xaml /// </summary> public partial class ucPopupMnu : UserControl { // Register the routed event public static readonly RoutedEvent MenuItemSelectedEvent = EventManager.RegisterRoutedEvent("MenuItemSelected", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(ucPopupMnu)); // .NET wrapper for routed event public event RoutedEventHandler MenuItemSelected { add { AddHandler(MenuItemSelectedEvent, value); } remove { RemoveHandler(MenuItemSelectedEvent, value); } } public ListBoxItem SelectedItem { get { return (ListBoxItem)lstColors.SelectedItem; } set { lstColors.SelectedItem = value; } } public ucPopupMnu() { InitializeComponent(); } private void lstColors_MouseDoubleClick(object sender, MouseButtonEventArgs e) { ListBoxItem selection = (ListBoxItem)lstColors.SelectedItem; //txtSelectedColor.Text = selection.Content.ToString(); // Raise the routed event "selected" RaiseEvent(new RoutedEventArgs(ucPopupMnu.MenuItemSelectedEvent)); } } }