views:

104

answers:

2

In a WPF application, I've got my events centralized in one class like this:

public class EventFactory
{
    public static void Button_Edit_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("you clicked edit");
    }

    public static void Button_Add_Click(object sender, RoutedEventArgs e)
    {
        MessageBox.Show("you clicked add");
    }
}

so that I can reuse them in many Windows like this:

public Window1()
{
    InitializeComponent();

    ButtonEdit.Click += EventFactory.Button_Edit_Click;
    ButtonAdd.Click += EventFactory.Button_Add_Click;
}

This works fine, but now I want the events to act on the Windows which call them which I was able to do when the event handlers were simply in the code-behind for each window.

How can I e.g. inject a window object into the event handler so that that event handler can directly manipulate it, something like this:

ButtonEdit.Click += EventFactory.Button_Edit_Click(this);
+2  A: 

One way:

ButtonEdit.Click += EventFactory.ForConsumer<Window1>().Button_Edit_Click;

In other words, turn your factory class into an actual factory that creates objects based on some context. In this case, the context is the object consuming the events.

Another way:

public static void Button_Edit_Click(object sender, RoutedEventArgs e)
{
    Window window = Window.GetWindow(sender as DependencyObject);
    MessageBox.Show("you clicked edit");
}

I'm not particularly fond of either of these approaches, but there you go.

HTH,
Kent

Kent Boogaart
Shouldn't the first approach be `ButtonEdit.Click += EventFactory.ForConsumer(window1Instance).Button_Edit_Click;`?
João Angelo
I tried both of those, but on the (1) I don't need to pass the Type e.g. "Page1" with which I could call static methods, but I need the *instance* of Page1 itself so I can e.g. alter its Title property. And in (2) I am actually using UserControls, not Windows, and I can't find the equivalent of Window.GetWindow(...) for a UserControl.
Edward Tanguay
@Joao: yeah, that's what I meant - thanks. Got generics on the brain ;)
Kent Boogaart
@Edward: I was hoping you could extrapolate my answer to whatever works for you. For #1, see Joao's comment. For #2, you could search up the visual tree using `VisualTreeHelper`.
Kent Boogaart
thanks for your answers kent, I needed Joao's code to create a working solution but works well now, VisualTreeHelper also sounds useful, will have to explore that
Edward Tanguay
+1  A: 

You can try something like this:

public class CommonEventHandler
{
    private CommonEventHandler() { }

    private object Context { get; set; }

    public static EventHandler CreateShowHandlerFor(object context)
    {
        CommonEventHandler handler = new CommonEventHandler();

        handler.Context = context;

        return new EventHandler(handler.HandleGenericShow);
    }

    private void HandleGenericShow(object sender, EventArgs e)
    {
        Console.WriteLine(this.Context);
    }
}

class Program
{
    static void Main(string[] args)
    {
        EventHandler show5 = CommonEventHandler.CreateShowHandlerFor(5);
        EventHandler show7 = CommonEventHandler.CreateShowHandlerFor(7);

        show5(null, EventArgs.Empty);
        Console.WriteLine("===");
        show7(null, EventArgs.Empty);
    }
}

You need to adapt the types to suit your needs but it shows the general idea.

João Angelo
thanks for the code, works well as it is, this is a simple useful pattern to move events out of code behind
Edward Tanguay