Silverlight 5 Domain Model Event Handler being called incrementally - silverlight

Ok ... next question. I am using Silverlight 5 C# 2012 and have gotten to a point where I could use a little help. I am using the Domain Model to call methods to return information and I discovered that if I hit the same button more than once, the method call happens incrementally. One call for the first click, two calls for the second click, three call for the third, etc.
Please check out the simple code below and if you can provide any insight as to why this is happening, I would greatly appreciate it.
In the Service Layer:
Interface:
[OperationContract]
string GetEnteredString(string strText);
Class:
public string GetEnteredString(string strText)
{
return "You entered: " + strText;
}
In the Silverlight Application:
private void btnGetText_Click(object sender, RoutedEventArgs e)
{
service.GetEnteredStringCompleted += new EventHandler<CARE_WCF.GetEnteredStringCompletedEventArgs>(service_GetEnteredStringCompleted);
service.GetEnteredStringAsync(txtTester.Text);
}
private void service_GetEnteredStringCompleted(object sender, CARE_WCF.GetEnteredStringCompletedEventArgs e)
{
MessageBox.Show(e.Result.ToString());
}
This seems pretty darn straight forward at first glance, but the call to the GetEnteredString method just keeps stacking on top of itself. I think it's because of the += in the Click event but I could be wrong.
Thank you in advance for any insight! I really appreciate it.
Eric

You have to unsubscribe from the event in Completed function like :
service.GetEnteredStringCompleted -= service_GetEnteredStringCompleted;

Related

Mouse freezing/lagging when hit breakpoint

Goal: To be able to find point(X,Y) of element on windows desktop application which been clicked without performing click itself.
Not working solution
I've added mousekeyhook Nuget package to my .net core WPF application, it working fine ( when click and event raising with correct position), but each time that program hit breakpoint( for specific below example - at M_Events_MouseDown method) the mouse starts to lag for about 20 seconds.
Also i have found that in WinForms application it works smoothly
MouseKeyHook implementation:
public partial class MainWindow : Window
{
private IKeyboardMouseEvents m_Events;
public MainWindow()
{
InitializeComponent();
SubscribeGlobal();
}
private void SubscribeGlobal()
{
Unsubscribe();
Subscribe(Hook.GlobalEvents());
}
private void Subscribe(IKeyboardMouseEvents events)
{
m_Events = events;
m_Events.MouseDown += M_Events_MouseDown;
}
private void M_Events_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
Console.WriteLine($"Mouse down :{e}");
}
private void Unsubscribe()
{
if (m_Events == null)
return;
m_Events.MouseDown -= M_Events_MouseDown;
}
}
This is a known issue and low-level hook behavior by design.
When you hook into the mouse event processing chain, your code is one of many other processors. Every hooked piece of code has a possibility to suppress or modify further processing. Nevertheless, there is a time limit to do so. If you set a breakpoint, windows call your code, your code does not respond, a timeout occurs and it starts over.
See a similar question for details. The second answer with more upvotes is the better one.: Low level mouse hook - mouse freeze on breakpoint

Integration Testing of WPF GUI: How do I identify that current work was finished

I want to run integration UI tests on my WPF application, and I'm not sure how to detect when the current test has finished so that I can proceed to the next one.
Simplifying, suppose I have a button on my window. When the button is clicked I disable it, I modify the model, and I re-enable the button. Once it detects that the model has changed, WPF changes the view on the screen.
Now I want to run a test that simulates clicking the button again and again. To click the button I’ll use automation, as described in this SO question. But how do I know when the work is finished and the display updated, so as to "click" the button again? Do I hook the botton’s IsEnabledChanged, or is there some global indication that the current cycle of processing has finished?
Edit: What was missing in my description is that I want the user to see the interim results on the screen. For example, if the test has 10 phases I want the user to see something like a Step Counter label with values 1 .. 10 appearing on the screen, and not just the number changing immediately from 1 to 10. See my answer below.
how do I know when the work is finished and the display updated, so as to "click" the button again?
According to your description, you said When the button is clicked I disable it, I modify the model, and I re-enable the button.
Therefore, I can only assume that when the model has changed, the Button will be re-enabled. So you could either attach a handler to the model's NotifyPropertyChanged event, or as you suggested, add a handler for the IsEnabledChanged event.
Here is how I managed to get it working. This might be trivial - I'm a novice with GUI. I'm just posting it here in the hope it'll help other novices like me :)
Anyhow, what I used is a two button solutions: Test and Step. Test starts the testing sequence, Step runs each step of the tests. The Step buttons interact with an Integration Tester By Steps helper.
The helper receives an Init with the Number Of Commands as parameter, (currently the helper generates random commands by itself, so it just needs to know how many commands to generate). The helpe provides a Step method to execute the next command, and a Needs More Steps property to indicate whether testing should continue.
The helper derives form INotifyPropertyChanged and has a Counter dependency property that is displayed on the main window.
The states of the Test and Step buttons are controlled by three helper methods: SetButtonsFor_OutsideTesting, SetButtonsFor_InsideTestingOutsideAnyStep and SetButtonsFor_InsideTestingInsideAStep.
First, I verified that everything is working manually, and then I added a timer and automated the process using the Stack Overflow suggestions on how to programmatically click a button in WPF and how to make a WPF Timer Like C# Timer.
Now, here's the Main Window's code:
private void Test_Click(object sender, RoutedEventArgs e)
{
SetButtonsFor_InsideTestingOutsideAnyStep();
RunTheTestBySteps();
}
public readonly IntegrationTesterBySteps _integrationTesterBySteps =
new IntegrationTesterBySteps();
void RunTheTestBySteps()
{
SetButtonsFor_InsideTestingOutsideAnyStep();
IntegrationTesterBySteps.Init(10);
StartTheTimer();
}
private void StartTheTimer()
{
DispatcherTimer = new DispatcherTimer();
DispatcherTimer.Tick += DispatcherTimer_Tick;
DispatcherTimer.Interval = new TimeSpan(0, 0, 1);
DispatcherTimer.Start();
}
private void StopTheTimer()
{
DispatcherTimer.Stop();
DispatcherTimer.Tick -= DispatcherTimer_Tick;
}
private DispatcherTimer DispatcherTimer { get; set; }
private void DispatcherTimer_Tick(object sender, EventArgs e)
{
if (!BtnStep.IsEnabled) return;
ClickTheStepButton();
CommandManager.InvalidateRequerySuggested();
}
private void BtnStep_Click(object sender, RoutedEventArgs e)
{
SetButtonsFor_InsideTestingInsideAStep();
IntegrationTesterBySteps.Step();
if (this.IntegrationTesterBySteps.NeedsMoreSteps)
SetButtonsFor_InsideTestingOutsideAnyStep();
else
{
SetButtonsFor_OutsideTesting();
StopTheTimer();
}
}
private void ClickTheStepButton()
{
var peer = new ButtonAutomationPeer(BtnStep);
var invokeProv = peer.GetPattern(PatternInterface.Invoke)
as IInvokeProvider;
if (invokeProv != null)
invokeProv.Invoke();
}
void SetButtonsFor_InsideTestingInsideAStep()
{
BtnTest.IsEnabled = false;
BtnStep.IsEnabled = false;
}
void SetButtonsFor_InsideTestingOutsideAnyStep()
{
BtnTest.IsEnabled = false;
BtnStep.IsEnabled = true;
}
void SetButtonsFor_OutsideTesting()
{
BtnTest.IsEnabled = true;
BtnStep.IsEnabled = false;
}

Is there "LoadComplete" such an event in Windows Forms?

I want my windows form to be loaded first, render its children and all. After that load heavy data in it. This is why I am looking for any event which I could use just after form loading is complete.
Any thoughts on this?
I have never found a better solution than Activated; although that is raised every time the form receives focus - so you need to filter out all the times after the first:
bool _firstActivation = true;
void Form1_Activated(object sender, EventArgs e)
{
if (_firstActivation)
{
_firstActivation = false;
OnFirstActivation();
}
}
private void OnFirstActivation()
{
}
Perhaps you're looking for the Form.Shown event. If you're doing a lot of intensive work though, perhaps you should be using a background thread anyway to avoid locking up the UI.
Like MikeP said you want to handle the Form.Shown event just once. So just attach to the even and detach once done.
private void frmMain_Load(object sender, System.EventArgs e)
{
// Do stuff in form load.
Shown += FirstShown;
}
private void FirstShown(object sender, EventArgs eventArgs)
{
Refresh();
// Do something here
// Detach from this event.
Shown -= FirstShown;
}
I do that in a way that I fire a timer with duration of 1, and kill it in the event, and with that method, I know that message loop will be empty and form initialization will be complete when my event comes.
Event is set up from Form_OnLoad() method.

How do I call a webservice in the Application_Exit event?

How do I call a webservice in the Application_Exit event?
private void Application_Exit(object sender, EventArgs e)
{
TestWSSoapClient.ReleaseUserCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(TestWSSoapClient_ReleaseUserCompleted);
TestWSSoapClient.ReleaseUserAsync(UserToken);
}
The method below is no longer executed.
void TestWSSoapClient_ReleaseUserCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
}
Thank you in advance.
You can't call any web services when exiting by design, however this article might help you with an Javascript alternative.
Do you really need to get the response? You won't be able to get it as all threads will be closed at the end of the Application_Exit function. But if it doesn't matter, you can configure your "ReleaseUser" operation as OneWay.
As I didn't test it, it is only a supposition, but I think it should work (and if it doesn't, well, I will learn something)
Otherwise, as said before, javascript is the only way to go, but it won't work Out of Browser.

Silverlight Web Service

Below is the code i used to consume web servcie in SilverLight.
private void button1_Click(object sender, RoutedEventArgs e)
{
BasicHttpBinding bind = new BasicHttpBinding();
EndpointAddress endpoint = new EndpointAddress("http://loalhost/Service.asmx");
ServiceSoapClient client = new ServiceSoapClient(bind, endpoint);
client.RunHelloCompleted += new EventHandler<RunHelloCompletedEventArgs>(client_RunQwinCompleted);
client.RunHelloAsync(command);
}
void client_RunHelloCompleted(object sender, RunHelloCompletedEventArgs e)
{
txtProcess.Text=Process(e.Result);
}
I want to know a way that after i run RunHelloAsync(Command), I want to get the returned result without going to Completed event. Please advise me. thank you.
Simple answer : You can't. Everything in Silverlight is Asynchronous so there is no way to block after the client.RunHelloAsync(command) call and wait for the result.
Long answer : There are ways to simulate working with calls in a synchronous fashion, but the calls still being made asynchronously. Take a look at this thread for a few more answers.

Resources