Silverlight Application UI updating - c#

Hi I have a problem when I am working on my Windows Phone silverlight C# application.
So I want to do something like this
Press a button on page one. The button click handler calls a async method MakeRequest in other class to retrieve data. The async method will fire a event DataReadyEvent and has the result wrapped as DataEventArgs.The handler of this event will be in Page2. So after add a handler to this event, I navigate to Page2 from current page.
I want to retrieve data by a event handler in Page 2 code behind and update that on UI. But the event handler is static (so that I can add it by using Page2.handler_method_name in page1 code without creating a new instance of the page.). Since the handler method is static, I cannot use Dispatcher.Invoke and get back to the UI thread and update UI.
So in this case, anyone has any idea to it? I just want to call a async method in page1, and update result to UI in page2. Thank you

Here is an idea: don't make it static. Don't try to create problems for yourself by breaking simple OOP rules like encapsulation, etc and by finding some crazy workarounds around the framework you work with.
When you are in such a situation you should stop, look back and think because it is an indication that you do something completely wrong. Don't try to push it even further by finding hacks and workarounds. Rather you should refactor and reuse the correct paradigm.
For example, if you want to display the result on Page2, then there IS a Page2 ALREADY. So there IS an instance of it. Why do you want to use static handler then?
Probably because you don't have a reference to this page. That's fine, normally you shouldn't.
But when you finish your computation you can publish an event saying "hey, here is the task done". At that point you shouldn't care who is interested in this result, that's not the worker's concern.
Which means that the logic of the computation itself should probably be moved out from Page1. Really, pages concern is dome presentation logic, nothing more.
Page1 should make a request that some computation needs to be done. And here will be an external component (perhaps something in your ViewModel) to actually make it happen.
So when the result is ready to be consumed, you can simply push it into a ViewModel (update some observable properties or collections, etc), so if there is any UI (or many of them, or other components) interested in this data it will be automatically notified and the data will be displayed.
But please don't try to hack around, it will lead you to bigger pain in the future.

Related

Can I freeze my UI rendering while my form loads?

Is there any way I can pause all UI Update commands in Winforms?
Or I have a slight feeling I'm trying to go about this the completely wrong way, so is there another way around my problem: I basically load a saved state of a control, which loads new controls all over it. However I do some of this in the UI thread, and some of the data loading from another thread, which then fills the UI.
So the effect I have when it is loading is that the user can see a few of the controls appearing in one place, then moving to another place on the form, changing values, etc.
I'd like to get a loading screen instead of this and load the controls in the background. It's quite a large application and its not THAT important so redesigning my code isn't really an option.
Can I simply stop all Update() commands on a control while a method is executing?
You can use the SuspendLayout and ResumeLayout methods to wrap the setup of UI in one operation (without the update of the rendering).
Basically (assuming SomeMethod is in the form class):
private void SomeMethod()
{
this.SuspendLayout();
// all UI setup
this.ResumeLayout();
}
it really depends on your form logic, in general you should not overload the Load or Show method with too much things so that the form can be shown and drawn quickly and always look responsive.
in some cases it could help to use the SuspendLayout and ResumeLayout methods, see here:
Control.SuspendLayout Method

C# Progress Bar within a class?

Simply put, what is a good way to send the progress of some process back to a form from within a class outside the scope of the form?
EG: I have a Input object, a filepath is sent into the constructor of this object and it parses the file. I want to show the progress of reading in the lines of this file back to the user who is in a form outside the scope of the currently running method. Ultimately I will be displaying overall progress and per file progress.
Add an event to your class that the form can subscribe to. UpdateProgress or something like that. Your class would then raise the event every so often to let the form display the progress.
The best approach here would be a BackgroundWorker. It has a specal event ReportProgress (that handles the Invoke logic for you).
It is an easy way to do multi-threading. Follow a good example when implementing the RunWorkerCompleted event.

problems designing event driven communication

Im struggling a bit with a design issue. Im making a very simple gui system in c#. The code is meant to be reusable so Im looking for the most flexible solution here. The solutions I come up with seem to all have their drawbacks.
For simplicity lets pretend there are three classes: controller, button and the client code. The client code is the code using the gui system. It creates the controller and calls Update() on it. The controller creates a bunch of button instances and calls Update() on them. The buttons draw themselves and check for mouse clicks.
Now the problem is how do I get the fact that a button was clicked to the client code?
Option 1: Add GetButton(string name) to the controller class. The client code can then subscribe to the events defined in the button class => GetButton("but").MouseUpEvent += MouseUpHandler; The drawback to this is that this exposes Button.Update() which is, and should only, be used by the controller.
Option 2: Have the controller subscribe to all buttons and the client code subscribe to the controller. The drawback here is more parsing code in the client code as now all events are funneled through the controller, so the client has to check which button sent each event. I prefer to setup the flow of events in the initialization phase like in option 1.
Option 3: Add Subscribe/Unsubscribe methods to the controller for each event (SubscribeMouseUp(string buttonName, GUIDelegate del) etc.) Drawback is the controller api grows quickly.
So right now Im leaning towards option 1, but GetButton returns an interface (IClientButton maybe) that only declares the events, thereby hiding Update() from the client, but Im not sure if this is how interfaces are supposed to be used.
Any insight is appreciated.
Bas
Presumably this is an issue because Update() is public?
Presuming you've organized your button and controller into the same namespace would using internal protection suit your needs?
interface can be used that way, INotifyPropertyChanged is an interace with 1 item which is an event.
what about using RoutedEvents?
There's a 4th, maybe more popular option.
Have a dispatcher as a central location to register/unregister with. All event receivers register a callback with the dispatcher. All event generators send their events to the dispatcher.
It keeps the API cleaner and helps to untangle object referencing.
In your Controller, add two events - ButtonCreated and ButtonDestroyed.
public event EventHandler<ClientButtonEventArgs> ButtonCreated;
public event EventHandler<ClientButtonEventArgs> ButtonDestroyed;
The ClientButtonEventArgs is simply an EventArgs wrapper around your IClientButton interface.
Have your client code subscribe to both of these events. When the Controller creates a new button, have it fire the ButtonCreated event. The client code can then subscribe to the necessary Button events when it receives the event notification. Similarly, the Controller will fire the ButtonDestroyed event as necessary, allowing the client code to unsubscribe from the Button's events.
In this way, the entire sequence is event-driven. The client code reacts to the creation and destruction of a Button, which it seems like is what you're after.

Textbox and focus problems with Timer controls(asp.net)

I am needing to create something like a lock timer(a little thing that just updates a lock time in a database). I thought the Timer control would suite my needs, but whenever the Timer control causes a partial post back, recently typed text in a textbox can disappear(inbetween the post back begin and post back end) and it loses focus.
Because this is only a lock timer, I do not need to refresh any part of the screen, I basically just need to tell the server "hey, don't free my lock, I'm still on this page". So is a Timer control even necessary? Is there an easier way to do this is pure javascript? The only thing I need to know is an ID, which could be kept as a hidden field(and therefore accessible from javascript by DOM)
anyone have any input on how to tune the timer control or a quick javascript way to do it?
edit:
also, I have the updatepanel that contains the timer control outside of the update panel containing the textbox control
If I understand it correctly you need a method which will update the datetime in the database at periodic intervals.
For that you can simply use Ajax. The window.setInterval is a JavaScript function which will fire a piece of code at regular intervals.
window.setInterval(foo,5000);
The above code fires the foo method every 5 seconds.
The only thing you need to lookup is how to call the database. Since, you are already using MS Ajax I suggest you check out ScriptManager control which contains a section for services. Check out the following post which consists of a simple example of how to call WebService methods using MS Ajax:
http://azamsharp.com/Posts/83_Using_FireBug_Profiler_to_Dig_Deep_into_MS_AJAX_and_JQuery_API.aspx

C# How To: Trying to call button twice in same class?

Did some searches here & on the 'net and haven't found a good answer yet. What I'm trying to do is call a button twice within the same class in C#.
Here's my scenario -
I have a form with a button that says "Go". When I click it the 1st time, it runs through some 'for' loops (non-stop) to display a color range. At the same time I set the button1.Text properties to "Stop". I would like to be able to click the button a 2nd time and when that happens I would like the program to stop. Basically a stop-and-go button. I know how to do it with 2 button events, but would like to utilize 1 button.
Right now the only way to end the program is the X button on the form.
I've tried different things and haven't had much luck so far so wanted to ask the gurus here how to do it.
BTW, this is a modification of a Head First Labs C# book exercise.
Thanks!
~Allen
You would need to use Multithreading (launch the process intensive code asynchronously in a separate thread), for instance, using the BackgroundWorker object in .NET 2+. This would be necessary because your UI will not respond to the user's click until the loop running in the Start method is completed. It is quite irrelevant if you use the same button or another one to toggle the process, because the processor is busy processing the loop.
The BackgroundWorker has a property called WorkerSupportsCancellation which needs to be true in this scenario. When the user clicks Stop you would invoke the CancelAsync method of the BackgroundWorker.
See MSDN for a good example. Also DreamInCode has a good tutorial which seems quite similar to your requirement.
Why not create two buttons, hide one when the other is visible? That should be a lot of easier to handle.
Or you can add a bool field to indicate which operation branch to execute.
One simple solution would be to add a boolean member to your form that is, e.g., true when the button says "Go" and false when the button says "Stop".
Then, in your button's event handler, check that boolean value. If the value is true, then start your operation and set the value to false when you change the button's text to say "stop". Vice-versa for the other case. :)
There are other techniques that I might prefer if this were production code, perhaps including considering the design of the form more carefully, but as this is clearly a learning exercise I believe that a simple boolean flag indicating the current state of the form is just what you're looking for.
Note that I would strongly discourage you from checking the value of the button text to determine what state the object is in. Whenever possible, as a general rule of good design, you want your visual state to be "decoupled" from your underlying object's state. That is to say, your visual widgets can depend on your underlying objects, but your underlying objects should not depend on your visual widgets. If you tested the text of the button, your underlying logic would depend on your visual state and that would violate this general rule.
If your problem is related to the fact that you can't cancel the operation while it's being performed, you'll want to look into using a BackgroundWorker to perform your long-running activity.
Another option would be to check the current text on your button to determine what to do:
void btnStartStop_Click(Object sender, EventArgs e)
{
if (btnStartStop.Text == "Go")
{
btnStartStop.Text = "Stop";
// Go code here
}
else
{
btnStartStop.Text = "Go";
// Stop code here
}
}
Are you getting your second button click event? Put a breakpoint in your click handler and run your code. When you click the second time, do you ever hit your breakpoint?
If your loop is running continuously, and it is in your button click handler, then your loop is running in the UI thread. You probably don't get to "see" the second button click until after the loop is completed. In addition to the branch code that you see above, try either inserting a DoEvents in your loop processing (this is a place where your loop will temporarly give up control so that messages can be processed). Or, (better) have a look at the backgroundworker class -- do most of your processing in a different thread, so that you UI can remain responsive to button clicks.
Cerebrus is right about using the Background Worker thread. However if you are doing a WPF app then it won't be able to update the UI directly. To get around this you can call Dispatcher.BeginInvoke on the main control/window.
Given code like:
Private Delegate Sub UpdateUIDelegate(<arguments>)
Private Sub CallUpdateUI(<arguments>)
control.Dispatcher.BeginInvoke(Windows.Threading.DispatcherPriority.Background, New UpdateUIDelegate(AddressOf UpdateUI), <arguments>)
End Sub
Private Sub UpdateUI(<arguments>)
'update the UI
End Sub
You can call CallUpdateUI from the Background Worker thread and it will get the main thread to perform UpdateUI.
You could set the Tag property on the button to a boolean indicating whether the next action should be "Stop" or "Go", and reset it each time you click the button. It's an Object property, though, so you'll have to cast it to bool when you read it.

Categories

Resources