Need help with Dispatcher.PushFrame style process blocking in WPF page - wpf

I am using Dispatcher.PushFrame to block my code while allowing the UI to refresh until a long running process is done. This works as expected, so long as my call to Dispatcher.PushFrame is from a button click event. If, however, I use this same code during the Page’s Loaded event or constructor, the UI does not refresh, and so never paints. As a random experiment, I tried using Window.ShowDialog from the constructor, and it does allow the UI to paint, even though control is blocked until the modal dialog closes. Can anyone offer a solution to allow this functionality from the Page Loaded event using Dispatcher.PushFrame or some other manual mechanism?
As an addendum, if I minimize or maximize my window, the UI paints and I can interact with it normally, but not until I manually perform the resize.

From my readings in MSDN on Object Lifetime Events and stumping around in Reflector it appears that the Loaded and Unloaded events are not raised in the same manner as other events. Internally a BroadcastEventHelper class is used, which coordinates the various Loaded events amongst every element in the visual tree before eventually raising them at the DispatcherPriority.Loaded level.
I believe this is why you're seeing this behavior.
As for a concrete solution, I suggest long running tasks not be placed in the Page.Loaded event handler and instead a BackgroundWorker or Task be issued to complete the work.

Related

Is it possible to call WebBrowser.InvokeScript async from an WPF application?

I want to call a JavaScript function in a hosted WebBrowser. My JavaScript function is slow (in UI not retrieving data or ajax) and I want to make my WPF interface responsive while the JavaScript function is being executed.
You can call your JavaScript function asynchronously (e.g., upon a timer), but asynchrony doesn't assume multithreading, the function will still be executed entirely on the main UI thread. And you cannot use a separate thread for this, because the underlying WebBrowser ActiveX control is an STA COM object.
If you really have to perform a lengthy UI update work inside your JavaScript function, the right way of doing this would be to throttle the update logic and execute it in multiple steps, each step asynchronously, to keep the UI thread responsive. You can do this using setTimer or jQuery's delay. A more well-structured approach would be to use jQuery Deferreds, as explained here.
We solved our problem somehow with a trick, might be useful for others.
After a call to WebBrowser we start a new window in a new UI thread and put our new window on the previous window (which its thread is busy doing JavaScript calculation in WebBrowser) , so we are able to somehow show progress-bar and loading page while doing heavy drawing in our html .

WPF MVVM: Decouple view bindings and dynamically setting bindings

I'm writing a fairly large WPF application that is following the MVVM structure. I would like to run my UI in basically 2 modes. The first being the normal day-to-day operational mode. The second is one that I've been wondering about for a while now...I would like to be able to run it in a "configure" mode where the user will see the UI in more or less the same fashion as the normal mode, except that a popup window would appear when they hover over (or maybe click) a control. This popup would allow the user to change certain bindings related to that control. I don't want to expose every property (or every control).
For example:
There is a TextBlock that has a binding to a pressure signal, now that user wants to change this binding to a temperature signal. They could start the UI in config mode, navigate to the screen with the TextBlock, select it, and see the Text property in a popup which they can then change to the new temp signal. This is a simplified exampe, but basically what I'm looking to do.
Is this possible? Remember the UI would have to write to the the View (XAML). Any help is appreciated.
P.S.
This would be a very useful but rarely used feature. It would be ok to maybe have 2 projects which ustalize the same View but different ViewModels and Models...at least that's what I've been thinking might be needed. Even if the normal mode UI would have to be recompiled after using the configure mode UI.
Every popup window should have its own VM (or they could share if it turns out to be an overkill due to small number of properties per popup) and communicate with the main VM via the message bus.
Store your bindings as User Settings and when the message arrives from the popup window VM, carrying the new binding as a payload, main VM would get that payload and save the appropriate user setting by simply calling Settings.Default.Save();
Based on your description, no reason to make it more complicated than that IMO...

Winform not visible while debugging

I have an application that manipulates with some files in certain matter and have progressbar and textbox. When I debug (VS2010), the app window is not visible, but the app does all the work that it suppose to. If I wanted to create invisible winform application I would probably have to bust my brains out to do so. Now I have one I don't want. How about that? Any ideas how to fix this?
The OP is performing work in the form's initialization phase. During that phase, the form is not yet shown and will not be shown untill all the work is done.
The solution is to move the work code from the form's initialize method to a separate method, that is called only after the form is shown. This method should perform the work on a separate thread to ensure the GUI stays repsonsive, the process can be cancelled and reports back to update the progress bar.

WPF - Navigation blocks application (poor performance)

I have a WPF application which generates MIDI notes (a sequencer).
Besides the UI thread, there is a timer thread which triggers notes. In general, the timing is ok, but I have the following problem: Whenever I do any navigation, the application seems to "block" (i.e. the timer "stumbles" and the output stops for a short time). This happens when I e.g. open a new window or perform a navigation on a navigation window.
This also happens when I navigate to a page which is already instantiated and has been shown before.
Does anyone have any ideas?
EDIT: I think the actual question is: Does anyone know of a way to make navigation faster?
I'm not sure, but wouldn't your eventhandler (_midiInternalClock_Tick) be executed in your UI thread?
So the MidiInternalClock might be executing in another thread, but the handling of the ticks wouldn't. Like I said, not sure about this.
You might want to separate the code that works with the Midi toolkit to a separate class and then construct the clock en handle it's events in a different thread.
If that doesn't help, I'm at a loss. I guess you would then best ask your question on the CodeProject page.

Injecting Mouse Input in WPF Applications

I've been working on injecting input into a WPF application. What makes this project hard is that I need to be able to inject the input into the application even though it's running in the background (i.e. another application has the input focus). Using the SendInput() function is therefore out of the question.
So far, I've got keyboard input working but am having trouble injecting mouse input.
I used Spy++ to observe the window messages that get sent to the WPF window when I physically click the mouse button. I then simply craft these same mouse messages (such as WM_LBUTTONDOWN and WM_LBUTTONUP) manually and send them explicitly to the WPF window to emulate mouse input.
Unfortunately, this doesn't work as expected (not even when I, for testing purposes, have set the WPF window as the foreground window).
I've added a button to my test WPF window which when clicked displays a message box. Injecting the appropriate mouse messages when I've manually positioned the cursor over the button doesn't cause the button to be clicked, however (i.e. the clicked event isn't fired by the WPF framework).
If I add a handler for mouse clicks on the actual dialog (the client area), that handler does get called if I position the cursor over the dialog itself and inject the same window messages as before:
this.MouseLeftButtonDown += WndMouseDown;
public void WndMouseDown(object sender, EventArgs e)
{
...
}
Strangely enough, if I change the push mode of the button to Press (i.e. it's considered clicked on mouse down rather than the default mouse up), the button clicked event is now fired when I inject the same messages as before. (It's worth mentioning that the handler from the example above correctly fires for both mouse downs and ups, so it'd seem the WPF framework does process both messages successfully.)
It seems like there are some other criteria that need to be fulfilled in order for a mouse clicked event to be fired by the WPF framework. Does anybody know how mouse input is handled internally in WPF, or why it's not interpreting my mouse up and down messages as a click on the button?
(It's worth mentioning that this approach [sending window messages] works fine on ordinary Win32 windows, such as the Start->Run dialog. The difference here is that WPF only has one physical Win32 window and the rest is WPF specific, which means all window messages go to that top-level window rather than the actual button.)
I've been searching high and low for an answer to this and would appreciate any thoughts or ideas.
I'd highly suggest going the UIAutomation route. You create an AutomationElement by window handle. Crawl to the button and invoke it. I'd just like to know how you managed to get the keyboard input working. I am currently trying to resolve the converse issue. How to get a WPF window (I've managed to get a hWnd to it via Win32 calls), to respond to virtual keyboard messages. I've logged ++spy sessions on the window in question and replicated it's input without success.
Use UI Automation to do this - trying to manually simulate input via window messages is a textbook mistake, like trying to start a land war against Russia.
Your strategy is basically sound but in order to send a message to a window owned by another process you must first register the message.
Here is an article explaining the whole business. The sample code is unfortunately in VB but I'm sure that won't stop you.

Resources