How manage raising events of UserControls with TestStack.White? - c#

I'm testing my wpf application and I need to verify if certain usercontrol events correctly raise or not like, for example, Loaded/Unloaded events.
I've already created my UserControl class (I'm using DevExpress WPF Controls) because I know that TestStack.White doesn't support natively third party controls, the code is this:
[ControlTypeMapping(CustomUIItemType.Custom, WindowsFramework.Wpf)]
public class UserControl : CustomUIItem
{
public UserControl(
AutomationElement automationElement,
ActionListener actionListener)
: base(automationElement, actionListener)
{
}
protected UserControl()
{
}
public event RoutedEventHandler Loaded;
public event RoutedEventHandler Unloaded;
}
but now I don't understand how I can verify events raising or not. Does anyone help me? Thanks

Related

Correct way to pass events from a low level layer to UI? [duplicate]

I have a winform winform1 and 2 user controls control1 and control2 on this form
Now I want to define a custom event, which is raised/fired in control1 and received in control2. The event should be global and not directly defined in control1. control2 should not know about the existence of control1.
The event should also be raised by other controls. How is the C# code for that? Do I need something like a publisher class?
What you describe looks like the Mediator pattern, in which objects communicate through messages. These messages can be implemented as events, callbacks, or any other mechanism.
You could use an implementation like MVVM Light's Messenger class (this framework is intended for use with WPF and Silverlight, but you can get the code for this particular class and use it in WinForms)
// Register for a specific message type
Messenger.Default.Register<TypeOfTheMessage>(this, DoSomething);
...
// Called when someone sends a message of type TypeOfTheMessage
private void DoSomething(TypeOfTheMessage message)
{
// ...
}
// Send a message to all objects registered for this type of message
Messenger.Default.Send(new TypeOfTheMessage(...));
A big advantage of the Messenger class over a static event is that it uses weak references, so it doesn't prevent garbage collection of subscribed objects, which reduces the risk of memory leaks.
See this link for details about the Messenger class
You can use a static event:
public static class MyGlobalEvent {
public static event EventHandler MyEvent;
public static void FireMyEvent(EventArgs args)
{
var evt = MyEvent;
if (evt != null)
evt(args);
}
}
Subscribe in the usual way:
MyGlobalEvent.MyEvent += args => Console.WriteLine("Event Was Fired.");
Fire as you see fit:
MyGlobalEvent.FireMyEvent(new EventArgs());
So you can make your form publisher(and a mediator between controls), and all of your controls will be subscribers that will be notified on event.
An event occurred in a control, form will be notified and event handler on form will notify other controls that subscribed to this event.

mvvm binding custom event in custom window with viewmodel

I have the following scenario that I am hoping to find a resolution for, I have a custom Window class and I have created an event as below (i have remove some of the code for brevity)
public class AeroWindow : Window
{
public delegate void SystemMenuEventHandler(object sender);
public event SystemMenuEventHandler Exit;
...
public override void OnApplyTemplate()
{
...
var exitButton = this.GetTemplateChild("SM_ExitButton") as Button;
if (exitButton != null)
{
exitButton.Click += (sender, args) => { this.OnExit(); };
}
}
protected virtual void OnExit()
{
if (this.Exit != null)
{
this.Exit(this);
}
}
}
I am using MVVM with Calibutn.Micro and i have a ShellViewModel and ShellView (the ShellView inherits from AeroWindow)
What I would like to know is the following:
How should I correctly create custom events, is the above correct?
How do i then bind to said "event" in the view model
Can the same method of event be used to bubble the events from one view model to another (for example I have the ShellViewModel which initially loads a LoginViewMode (UserControl) and that in turn loads a MainViewModel (UserControl), if I have an event on the Window called Exit can the ShellViewModel subscribe to that and bubble it to the loaded view or should the loaded view subscribe to the window events)
I know that is a number of questions but they are all related to the same thing and I am hoping that someone can provide an answer.
Let me try to answer each of your questions
How should I correctly create custom events, is the above correct?
I think what you did above is correct or you can add an event handler like the usual.
If you're talking about custom events where you will create your own event aside from the built in events of a class, you can actually do that just create a delegate and an event within your class.
How do i then bind to said "event" in the view model
I don't think you want to bind events, what you want to do is to bind commands. You can try to read about ICommand, Relaycommand,
DelegateCommand. You can create an ICommand property in your
viewmodel then bind it to the Command property of the button. There
are also some tools that allows you to bind to events, try to look
for some libraries that offers EventToCommand
Can the same method of event be used to bubble the events from one view model to another (for example I have the ShellViewModel which initially loads a LoginViewMode (UserControl) and that in turn loads a MainViewModel (UserControl), if I have an event on the Window called Exit can the ShellViewModel subscribe to that and bubble it to the loaded view or should the loaded view subscribe to the window events)
In this scenario, where two viewmodel is involved, since you're using caliburn.micro, you might want to check on the
EventAggregator. This will allow you to publish an event from
one viewmodel and subscribe on another viewmodel. Then once the
publish is invoked, all the subscriber will be notified.

WPF execute a function before a particular event occurs?

Is there a way to execute a piece of code before an event occurs?
example when we say Expanded="OnExpand"
here the code inside OnExpand occurs after the Expanded event occurs. What if I want to execute a piece of code before that?
You can use the Preview Events
A possible work around for the expander not having a PreviewExpanded event is to handle the PreviewMouseDown event and do a hit test to see if its on the Toggle Button.
Alternatively it may be possible to extend the Expander Class something along the lines of
I did not test this at all no idea is it really works
public class MyExpander: Expander
{
public event EventHandler<EventArgs> PreviewExpanded;
public void OnPreviewExpanded()
{
PreviewExpanded(this,new EventArgs());
}
public override void OnExpanded()
{
PreviewExpanded()
base.OnExpanded();
}
}
If you're talking about the Expander control, you could subclass it and override the IsExpanded property, raising your own PreviewExpanded event before calling base.IsExpanded = value;
If whatever object you are working with supports this behavior it will be in a matching "Preview" event. So, these two events are a before and after matched set.
KeyDown()
PreviewKeyDown()
Expander does not have a preview event for Expanded, if that is what you are working with.

Writing a global custom event in C#

I have a winform winform1 and 2 user controls control1 and control2 on this form
Now I want to define a custom event, which is raised/fired in control1 and received in control2. The event should be global and not directly defined in control1. control2 should not know about the existence of control1.
The event should also be raised by other controls. How is the C# code for that? Do I need something like a publisher class?
What you describe looks like the Mediator pattern, in which objects communicate through messages. These messages can be implemented as events, callbacks, or any other mechanism.
You could use an implementation like MVVM Light's Messenger class (this framework is intended for use with WPF and Silverlight, but you can get the code for this particular class and use it in WinForms)
// Register for a specific message type
Messenger.Default.Register<TypeOfTheMessage>(this, DoSomething);
...
// Called when someone sends a message of type TypeOfTheMessage
private void DoSomething(TypeOfTheMessage message)
{
// ...
}
// Send a message to all objects registered for this type of message
Messenger.Default.Send(new TypeOfTheMessage(...));
A big advantage of the Messenger class over a static event is that it uses weak references, so it doesn't prevent garbage collection of subscribed objects, which reduces the risk of memory leaks.
See this link for details about the Messenger class
You can use a static event:
public static class MyGlobalEvent {
public static event EventHandler MyEvent;
public static void FireMyEvent(EventArgs args)
{
var evt = MyEvent;
if (evt != null)
evt(args);
}
}
Subscribe in the usual way:
MyGlobalEvent.MyEvent += args => Console.WriteLine("Event Was Fired.");
Fire as you see fit:
MyGlobalEvent.FireMyEvent(new EventArgs());
So you can make your form publisher(and a mediator between controls), and all of your controls will be subscribers that will be notified on event.
An event occurred in a control, form will be notified and event handler on form will notify other controls that subscribed to this event.

Interop WPF in WinForms, how to handle events from WPF control

I'm working with some WPF Interoperability in a WinForms application. I have the following set up.
WinForms UserControl WFControl
WPF UserControl GalleryControl
ListBox GalleryItems
ListBox ItemTemplate GalleryItem
Winforms hosting the GalleryControl, which has GalleryItems (ListBox) that has a ItemTemplate of GalleryItem.
Now in the WFControl I want to see when GalleryItems has it's SelectionChanged Event triggered.
My current attempts have tried to:
Handle the SelectionChanged Event in GalleryControl and have it raise a seperate public event that my winforms can read, but I can't handle the event like that since it's not a routed event. This would work if I could figure out how to handle that. applicable code:
public event ClaimGallery SelectedClaimChanged;
public ViewModels.InsuranceClaimViewModel ClaimViewModel { get; set; }
public int SelectedClaimID
{
get
{
return ((Models.InsuranceClaim) ClaimList.SelectedItem).ID;
}
}
public ClaimGallery()
{
InitializeComponent();
ClaimViewModel = new ViewModels.InsuranceClaimViewModel();
DataContext = ClaimViewModel;
ClaimList.ItemsSource = ClaimViewModel.InsuranceClaims;
ClaimList.SelectionChanged += ClaimSelectionChanged;
}
private void ClaimSelectionChanged(object sender, EventArgs e)
{
//This is the part that doesn't work
ClaimList.RaiseEvent(new RoutedEventArgs(SelectedClaimChanged, this));
}
I've also seen that I could potentially find the ListBox via some control tree browsing the subscribe to the actual event in the WFControl but I can't seem to figure how to do this in an interop'd control.
I have similar problems in my current project, and I'm solving it the way you describe.
The WPF controls re-raises a public (normal) event, that is then handled by the WinForms control.
Honestly I don't get the part where you are stating that is has to be routed in order to be handled by Winforms.
my winforms can read, but I can't handle the event like that since it's not a routed event
you use "+=" to handle this one ...

Categories

Resources