I ran into the following problem with my kiosk application:
I have a window with some thumbnails. When the user clicks on a thumbnail, another window (docview) with info is displayed and in the center a document is shown..
I would like to have the docview visible instantly and then start loading the document (the document loading takes 1-3 secs)and add it to the interface afterwards.
At the moment when I click a thumb, the interfaces freezes for a second or two, and then the docview is visible with the document already..
This is what I do:
viewgrid.Children.Add(docView); // the main window uses this grid to display the windows
viewgrid.InvalidateVisual();
viewgrid.UpdateLayout(); // at this point I would like to have the docView visible
docView.showDocument(); //and afterwards, the loading of the document should start and be also visible eventually..
I tried using the LayoutUpdated event with no success..Also putting the showDocument in a separate thread didn't help either..I also read about Application.DoEvents(), but that's deprecated and seemed bad practice anyway..
How should I resolve this?
Thanks in advance!
You need to use a BackgroundWorker object to load the document. You said you tried threading, and it didn't work, but you need to get threading to work and I recommend you use a background worker.
http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker(v=vs.110).aspx
I am not sure what type of document you are loading, but I loaded a RichText file using Binding as described here:
http://www.rhyous.com/2011/08/01/loading-a-richtextbox-from-an-rtf-file-using-binding-or-a-richtextfile-control/
You would do the same thing only you load the document in a BackgroundWorker. Once the document is loaded, you update the bound property and the UI will update.
You can try to use async bindings. Or do it manually with another thread and Dispatcher. But it depends on that your ShowDocument is doing and that is slow.
Related
i´ve got a problem. i have multiple threads. each thread shall create a new tabpage. this tabpage shall contain a webbrowser element. the elements are not there yet. they shall be generated after the single threads (up to 20) have been started.
so, i´ve got everything right, i think. i´ve got threads, which call a delegate (as STA Thread) and after working the thread and adding the controls, everything is right, i dont get errors. But every time, the tabe page (including the browser) is "added", there will be no changes in the form. there is no error, but also nothing appears on the form.
what am i doing wrong?
this is the call
frmMain.navigateBrowser("http://example.com")
and then, in the "navigateBrowser" function i will generate some elements and then finally add the elements to the form
tcMain.TabPages.Add(tmpTab)
I´ve had it in a timer before and was working it over a class, which saves the "command" (you! navigate now!) in a global var. but this method was too slow and now i want to try it directly over invoke.
That´s it, hope you can help me :)
I have a C# WPF application that is software captured using Open Broadcaster Software. When the application is in the foreground or even hidden by another application, it works just fine. However, if it is actually minimized, it stps updating. This makes sense, because usually, why would you need to redraw it if nobody can see it, but this is not true for this case. Is it possible to somehow force the UI to redraw? It would be possible to call a certain method every time a UI update is needed, because the code where I would need the UI to update/redraw looks something like this (simplified):
private void displaySomething(int something)
{
someRectangle.Fill = new SolidColorBrush(...);
// Redraw UI here
}
EDIT: "Update" might have been a misleading term here. "Redraw" may be better.
So if it works even the form is behind the other form, then do not let user to Minimize the form. Set yourWindow.ResizeMode = ResizeMode.NoResize;
I am using the Business Silverlight application. I have incorporated some MVVM into this and were off an running with it. We are using some telerik controls, mostly the ribbon control and the docking. We register all the telerik ribbon controls in the about.xaml.cs file, the method is DisplayUI - its here where we register the docking control then we register the ribbon after this. What happens is that when you click the ABOUT link it shows our first tab with buttons(perfect). when you click the HOME link next to the ABOUT link, we go back to the home page..but when you click the ABOUT link again it registers the controls again so we end up with two tabs that are the same.
Is there a way to check to see if this about.xaml.cs file has already been initialized? Im guessing that is has a handle on the first call in memory as I am able to see the first tabs rendering..
Thanks
here is the about code
public About()
{
InitializeComponent();
DisplayUI();
this.Title = ApplicationStrings.AboutPageTitle;
}
that display UI does all the work in registering the dockpanel and the ribbons. We'd like to not have the DisplayUI() called if this has already been rendered once.
If you do it by event handler can you unsubscribe from the event at the end of the method? Without seeing some code it's hard to work out what to change.
It's not the nicest way of doing it, but if this code needs to run once and only once then you could have a static boolean variable on the class set to false and when you call DisplayUI you check the value of this. If it's false you set it to true and run the method, and if it's true you just return.
I'm having some serious issues with a WinForm application that I'm working on.
Currently, I'm using Form1.ShowDialog(); to display a form. This code is contained in a background worker that looks for changes in a database. Using Form1.ShowDialog(); only allows 1 form to open at a time, even if there are multiple changes to the database. What I want to have happen is for multiple forms to open at once if there is more than one change in my database.
When I use Form1.Show();, the application blows up. For some reason, the Show() method makes the forms not display properly (all the elements in the form are missing).
Is there anything I can do to make my code work the way I want it to?
Edit: here's a code snippet
//result is a linq result
foreach (var row in result)
{
Form1 Form = new Form1();
Form.ShowDialog();
}
After a first look, I can tell you this:
Showdialog can't work the way you intend: this very method makes the owner inactive until the dialog is closed. In your case, the loop will pause at the first showdialog, then resume when you close the form, opening a new one and so on until the loop is finished.
As for the "show" problem, creating empty forms, I need more information. The rest of the code and the exception(s) you're getting.
Two points from the top of my head:
1) To open more then one form , use non modal (modeless) method (i think
the show() method). see for example http://msdn.microsoft.com/en-us/library/39wcs2dh.aspx
2) I am not sure you can call UI related method from a non UI thread. You might want to send an event to your UI thread from the worker thread and the UI thread will call the show method
I'm trying to make a listbox that display pictures from internet. The items are provided by binding itemsource to a model that contain the URL of the image and some other properties (title, desc, etc...).
Unfortunately, the list is very slow to load because WPF is trying to download all pictures from the web before showing the list and it makes the application freeze for 15 to 25 sec.
I've read that I should load the picture in an other thread but I don't know where I should do it and how ? Is it better to load all pictures directly in the model (by creating a thread pool only for that - but the problem is that it's not really part of the model/modelview) or is that better to create a background thread that will update directly the list when it has data ?
Thanks !
The easy way is to just just set the Binding.IsAsync property like this:
<Image ImageSource="{Binding propertyThatComputesImageSource, IsAsync=true}" />
Each access to propertyThatComputesImageSource will be done from a ThreadPool thread. If the thread creates the image with ImageCacheOptions.OnLoad, it will block until the image is loaded. So the UI will start up immediately and images will be loaded in the background and appear when they are available.
Binding.IsAsync is a good solution for ten or twenty images, but is probably not a good solution if you have hundreds of images and the load delay is long, since you could end up with hundreds of threads. In that case, load the images outside of databinding entirely by using ThreadPool directly:
ThreadPool.QueueUserWorkItem((state) =>
{
foreach(var model in _models.ToArray())
model.ImageSource = LoadOneImage(model.ImageUrl);
});
This may need to be extended with a Dispatcher.Invoke or two if the model's properties are DependencyProperty, since they can't be accessed from a separate thread.
This technique can be extended to spawn a fixed number of workers to load images and break the work up between them so multiple image downloads are happening, but the number of simultaneous downloads is limited so you don't end up with hundreds of threads.
A very simple approach would be to use a System.ComponentModel.BackgroundWorker (more info) in the view model. Here's a trivial example:
using (BackgroundWorker bg = new BackgroundWorker())
{
bg.DoWork += (sender, args) => FetchImages(viewModelObjectsNeedingImages);
bg.RunWorkerAsync();
}
The BackgroundWorker also makes it very convenient to cancel the background task.
You might also want to look at UI virtualization.
You can use this asynchronous observable collection to be able to bind your data source to your ListBox and still be able to load your data in another thread.
For an example on how to write such a thread, take a look at the BackgroundWorker documentation.
Also, you might want to consider lazy loading of your images, that is, only load the ones that are visible and a couple more at any time. This way, you gain two benefits: don't have to block the UI while fetching the images in your thread, and you can reuse your collection to only hold a few images at a time, preventing filling up the memory with lots of images at once if you plan on displaying, say, a couple of thousand. Take a look here for details on how such virtualization could be implemented.
Thanks to all of you !
All solutions should work :) In my case using IsAsync on the image of the ListBoxItem is good enough (at most there are 50 items). Actually, it's not retrieving the image from a network which was taking too much time !
Unfortunately my problem was somewhere else... It's related to a bug with proxy detection in .NET 3.5 which cause the application to load very slowly :
If there isn't any your_application_name.exe.config file in the application folder with the following code - .NET can take a lot of time to detect the proxy which freeze the application the first time that it accesses to a network :
<configuration>
<system.net>
<defaultProxy enabled="false"/>
</system.net>
</configuration>