Search code examples
c#wpfroutedeventargs

Passing variable with RoutedEventArgs?


I have the following class, and want to pass the text variable as RoutedEventArgs.

  public class CloseableTabItem : TabItem
  {
    String text;

    public CloseableTabItem()
    {
      //This style is defined in themes\generic.xaml
      DefaultStyleKeyProperty.OverrideMetadata(typeof(CloseableTabItem),
          new FrameworkPropertyMetadata(typeof(CloseableTabItem)));
    }

    public CloseableTabItem(String incomingText)
    {
      //This style is defined in themes\generic.xaml
      DefaultStyleKeyProperty.OverrideMetadata(typeof(CloseableTabItem),
          new FrameworkPropertyMetadata(typeof(CloseableTabItem)));
      text = incomingText;
    }

    public static readonly RoutedEvent CloseTabEvent =
        EventManager.RegisterRoutedEvent("CloseTab", RoutingStrategy.Bubble,
            typeof(RoutedEventHandler), typeof(CloseableTabItem));

    public event RoutedEventHandler CloseTab
    {
      add { AddHandler(CloseTabEvent, value); }
      remove { RemoveHandler(CloseTabEvent, value); }
    }

    public override void OnApplyTemplate()
    {
      base.OnApplyTemplate();

      Button closeButton = base.GetTemplateChild("PART_Close") as Button;
      if (closeButton != null)
        closeButton.Click += new System.Windows.RoutedEventHandler(closeButton_Click);
    }

    void closeButton_Click(object sender, System.Windows.RoutedEventArgs e)
    {
      this.RaiseEvent(new RoutedEventArgs(CloseTabEvent, this));
    }
  }

this is the code from Window1 which is the main class in a WPF app

  public partial class Window1 : Window
  {
    public static Window1 myWindow1;

    public Window1()
    {
      myWindow1 = this;
      InitializeComponent();
      this.AddHandler(CloseableTabItem.CloseTabEvent, new RoutedEventHandler(this.CloseTab));
    }

    private void CloseTab(object source, RoutedEventArgs args)
    {
      TabItem tabItem = args.Source as TabItem;
      if (tabItem != null)
      {
        TabControl tabControl = tabItem.Parent as TabControl;
        if (tabControl != null)
          tabControl.Items.Remove(tabItem);
      }
    }

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
      CloseableTabItem tabItem = new CloseableTabItem("THIS IS A TEST");
      MainTab.Items.Add(tabItem);
    }
  }

I want to be able to print the value of "String text" in the CloseTab method. How can I make "String text" be passed with RoutedEventArgs args?

Best Regards!

EDIT

I made some changes to the project and here is the code

ClosableTabItem.cs

namespace SampleTabControl
{
  public class CloseableTabItem : TabItem
  {

    String text;
    public delegate void TabsEventHandler(object sender, TabsEventArgs e);

    public CloseableTabItem()
    {
      //This style is defined in themes\generic.xaml
      DefaultStyleKeyProperty.OverrideMetadata(typeof(CloseableTabItem),
          new FrameworkPropertyMetadata(typeof(CloseableTabItem)));
    }

    public CloseableTabItem(String incomingText)
    {
      //This style is defined in themes\generic.xaml
      DefaultStyleKeyProperty.OverrideMetadata(typeof(CloseableTabItem),
          new FrameworkPropertyMetadata(typeof(CloseableTabItem)));
      this.text = incomingText;
    }

    public static readonly RoutedEvent CloseTabsEvent = EventManager.RegisterRoutedEvent("CloseTab", RoutingStrategy.Bubble, typeof(TabsEventHandler), typeof(CloseableTabItem));    

    public event TabsEventHandler CloseTab
    {
      add { AddHandler(CloseTabsEvent, value); }
      remove { RemoveHandler(CloseTabsEvent, value); }
    }


    public override void OnApplyTemplate()
    {
      base.OnApplyTemplate();

      Button closeButton = base.GetTemplateChild("PART_Close") as Button;
      if (closeButton != null)
        closeButton.Click += new System.Windows.RoutedEventHandler(closeButton_Click);
    }

    void closeButton_Click(object sender, System.Windows.RoutedEventArgs e)
    {
      TabsEventArgs args = new TabsEventArgs(CloseTabsEvent, text);
      RaiseEvent(args);
    }
  }
}

TabsEventArgs.cs

public class TabsEventArgs : RoutedEventArgs
{
    private readonly string text;

    public string Text
    {
        get { return text; }
    }

    public TabsEventArgs(RoutedEvent routedEvent, string text) : base(routedEvent)
    {
        this.text = text;
    }
}

Window1.cs

  public partial class Window1 : Window
  {
    public static Window1 myWindow1;

    public Window1()
    {
      myWindow1 = this;
      InitializeComponent();
      this.AddHandler(CloseableTabItem.CloseTabsEvent, new RoutedEventHandler(this.CloseTab));
    }

    private void CloseTab(object source, RoutedEventArgs args)
    {      
      TabItem tabItem = args.Source as TabItem;
      if (tabItem != null)
      {
        TabControl tabControl = tabItem.Parent as TabControl;
        if (tabControl != null)
          tabControl.Items.Remove(tabItem);
      }
    }

    private void btnAdd_Click(object sender, RoutedEventArgs e)
    {
      CloseableTabItem tabItem = new CloseableTabItem("THIS IS A TEST");
      MainTab.Items.Add(tabItem);
    }
  }

After making the changes (when I open more than 1 tab the app crashes), how would you access the "string text" in the CloseTab method in Window1 class?


Solution

  • Create a new subclass of RoutedEventArgs, add a property to it where you can store the variable to be passed and create a respective handler delegate of type void (object, YourNewEventArgs) which you then assign as the handler type of your event (which currently uses a normal RoutedEventHandler which hence only provides normal RoutedEventArgs).

    If the event then is to be raised you need to create your new event args and pass the variable to its property for that variable. How to get the value in the handler should be self-explanatory.