Virtualize WinForms ScrollableControl - Expensive Child Items - winforms

I am building a PDF Viewer using the Atalasoft DotImage libraries. They have a PDF Viewing component, but it doesn't support the Acrobat style PDF continuous layout, I have to display the pages a page at a time.
I need to build sort of a virtualizing scrollable control which has probably 3 PDFViewers in it, the current frame, and the ones immediately before and after. So my question is - how would I do this?
[I've been doing WPF for the last 3 years, and my WinForms experience has turned to mental mush.]
I need to be able to detect which viewers to open, and which to close. How?

You can do this with a Panel. Set AutoScroll = true and AutoScrollMinSize.Height = pages x control.Height. Implement the Scroll event handler and look at the -AutoScrollPosition.Y property to find out what the user is looking at. Change the Location property of the 3 controls and their Page property as necessary.

Related

Silverlight how to start a RadRibbonBar in "IsCollapsed" mode - property is ReadOnly

We have a Silverlight application with a RadRibbonBar at the top. The user can collapse it (not Visibility.Collapse) to just the menus with a double-click.
The IsCollapsed property is ReadOnly, but we need to retain the user preferences across runs of the app.
How do you programmatically set the IsCollapsed state of a RadRibbonBar?
Result
Silly me (and shows that the documentation is a little hard to find/follow). I had to google "RadRibbonBar IsMinimised" to find the actual page: http://www.telerik.com/help/silverlight/telerik.windows.controls.ribbonbar-telerik.windows.controls.radribbonbar-isminimized.html
Thanks to Stephen McDaniel for pointing out my error.
I think you might be confusing "Collapsing" a RibbonBar with the idea of "Minimizing" it.
Collapsing is something the RibbonBar does automatically when the window gets very small - which is why it's ready-only. From the documentation:
RadRibbonBar supports collapsing, which means that the ribbon may
automatically collapse to save space when the application is resized
to a smaller size.
But what you are describing (double clicking to get just the menu) is called Minimizing. From the documentation:
RadRibbonBar supports minimization, which means that the ribbon may be
hidden so that only its tab headers remain visible. In this state,
more screen real estate is available to the client area of the window.
And luckily, controlling Minimization via code is very easy. You can use the IsMinimized property:
IsMinimized - use this property to set or get the current minimize
state of the ribbon.
So you should be using the IsMinimized property instead of IsCollapsed.
You can check out the documentation links I provided above for more information.

A better way to show different wpf pages in mainWindow?

I have several Wpf pages in my project, these pages have different forms and ui control indide theme. The image below shows the mainWindow and there are two button.
I want to show a specific page when I click on + or Edit button using the Frame control which is highlighted.
apparenatly this woks:
Page1 me = new Page1();
mainFrame.Content = me;
But it has an IE navigation sound and a toolbar appears after going to page2.
any better way to show diffrent pages and not using a frame?
You may want to convert the Page into a UserControl. You can then put that control inside some other container, such as a Grid. You'll have to manually swap out the pages in the container when navigating, but it looks like you're doing that anyway.
The purpose of the Frame control is to allow navigation. If you don't want navigation, then don't use Frame. You can turn off the navigation toolbar, but that won't actually disable navigation - there are mouse buttons and keyboard shortcuts for navigating back.
If you just want to host a UI element without navigation, use something simpler, like a Border element - put the content in its Child property. You can change the Child as many times as you like at runtime.
I was able to set the frame control's NavigationUIVisibility to Hidden. This solved the problem for me. I am using Visual Studio 2010 though so it might not be applicable to older VS versions.
Ian Griffiths, what you suggest increases the workload on the developer substantially. And you are stepping outside of the underlying paradigm of XAML.
In my case I'm developing a game application and have chosen WPF as the UI platform as much as possible. For me that means a intro screen, character select, etc. The purpose of Pages is to encapsulate the navigational need of such an application.
I suspect your downvote is due to your statement "If you don't want navigation...". Upon re-reading the original posters question I see he does want navigation, he just wants it on his own terms. I would have voted you down too. YotaXP's solution neglects the issues with using a User Control, particularly if it may contain other User Controls. It looks like Chris Calvert came up with an actual solution to the poster's issue within the parameters of the problem.
I would be curios if I could override the navigation hotkeys and such within the existing paragimn but that's properly in its own thread.

Tweak WPF application performance which hosts hundreds of similar controls

We just ported our WinForms application to WPF.
However, performance decreased dramatically.
We have a User Interface which consists of about 200 UserControl.
Each UserControl is defined by a DataGrid (= 10 columns and 3-15 rows) as well as a Panel which hosts about 10 Buttons.
They are all hosted in a ScrollViewer.
(Please don't recommend to change the UI. I don't have any influence on that. The customer wants to be able to scroll to any of those UserControls.)
Since we ported the whole application to WPF the startup time increased by 100%. Using WinForms we experienced startup times of 15sec whereas now, we are struggeling with 30s.
Do you have any recommandations or ideas how to improve the loading time of a UI which consists of identical UserControl where simply each UserControl is bound to a different ViewModel? (Maybe some fast cloning of the UserControl instances or sth similar?)
I am using static Resources whereever possible.
I avoid Grids and Auto Sizing whereever possible.
Hope someone can share some thoughts on that one.
Thanks,
TH
First find out what is responsible for the time.
Maybe it's the controls, and maybe not. Often it's data structure.
I use the random-pause method.
My final solution is a custom Virtual Panel which supports items of dynamic height.
See http://rhnatiuk.wordpress.com/2006/12/13/implementing-a-virtualized-panel-in-wpf/ on how to create virtual panels.
My UserControls support two states:
- Initial
- Loaded
When the application is in idle the virtual Panel asks the Controls to change to the "Loaded" state. This loads the expensive UserControl.
Like that everything is lazy loaded and as soon as the user stops scrolling the visible items are loaded.
Maybe that helps others that are in the same sitaution.
TH
Try only to create the controls which are visible at the time, use lazy loading.
Maybe SnapsToDevicePixels=true can also help a little bit.
Guys, I thought about the following implementation. If anyone has concerns please let me know:
I will implement my own virtualizing "StackPanel" which supports smooth scrolling.
For the moment we assume that the height of my UserControls is fixed. One page could possibly hold 5 UserControls.
I will then go ahead and cache the preceding as well as the proceeding page:
In memory I will always hold 15 UserControls.
The content of the ScrollViewer is a Canvas.
Locations of my UserControls are adjusted by setting Canvas.Top.
Let's say the current situation is the following:
User has scrolled to page 2.
That means UserControl 5-9 is visible. Now the user scrolls down.
As soon as UserControl 5 becomes invisible I take the UC of the top (in this case UserControl 0), change its ViewModel and adjust its Canvas.Top so that it now is the Control which is at the End of the ControlCollection.
If the user scrolls any further I take UC 1, change its ViewModel and adjust its Canvas.Top.
And so on.
Furthermore I will set Canvas.Height manually so that the ScrollViewer represents the ScrollBars in a correct way.
I hope my explanation is understandable :)
What do you think?
BR,
TH
I remember reading something about how each instance of a UserControl loads the resource dictionary. So if you have as many of these as you describe it can take a while to load those.
Unfortunately I can't find the link I remember, but here is one that might help:
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/c9b6aa9f-5a97-428c-8009-5cda432b820c
Another thing to try is to not use UserControls and instead use a DataTemplate to build your datagrids and buttons. Or make a custom control template for the datagrid that includes the buttons. Either one might be faster.
Hope this helps.

Bookmarking WPF's FlowDocumentReader

I'm trying to save and restore the position of the document within a FlowDocumentReader to create a bookmark feature. There doesn't appear to be any seeking or search feature build in that is publicly accessible, leaving me with the following options:
Use FlowDocumentPageViewer instead,
saving the page each time the window
is resized and restoring it as soon
as the app is reloaded.
Loop through all the elements in the
Document property of
FlowDocumentReader, looking for the
first one that passes an on-screen
hit test, then using reflection to
use the internal search features to
bring that text back into view at a
later time.
Serialize the entire control.
Write my own document viewer control.
No. 1 is annoying because I'd have to forfeit the two-page and scroll viewing options of FlowDocumentReader. It also means seeking to the saved page before the user has a chance to resize the window. This is fragile and would probably break if the user say, switched resolutions between sessions.
No. 2 is a garish hack that would probably work, but be slow and break completely if the internals ever change.
No. 3 is looking like my best bet, but it only lets me save/restore the current position, not set arbitrary bookmarks.
No. 4 is just too much work. These controls are utterly fantastic, I just need this one feature...
Is there any other way to go about this?
This seems to work well for page views, but not for scroll view, which is okay.
reader is of type FlowDocumentReader, and document is the FlowDocument within it.
Set the bookmark:
var paginator = ((IDocumentPaginatorSource)document).DocumentPaginator as DynamicDocumentPaginator;
var position = paginator.GetPagePosition(paginator.GetPage(reader.PageNumber - 1)) as TextPointer;
bookmark = position.Paragraph;
Restore the bookmark:
bookmark.BringIntoView();

Tag cloud control for WinForms .NET 2.0+

How would you render a tag cloud within a .NET 2.0+ WinForm application?
One solution that I am thinking of would be using the WebBrowser control and generating to some ad-hoc HTML, but that seems to be a pretty heavy solution.
Am I missing something more simple?
How about creating a user control that implements the Flow layout control? You could have a method for "Add(string tagName)" that would create a link label on the fly and add it to the Flow Layout control. The Flow Layout works just like the web, in that controls added to it are put in the order of creation.
Then you only have to add some logic to resize the Link Label based on hit count for that tag.
Well, you'll want a control with these major features:
Automatic layout of variable sized string snippets
Automatic mouse hit testing
Those are a bit hard to come by in WF controls. A RichTextBox with ReadOnly = true gives you the automatic layout, but not the hit testing. A ListBox with DrawItem can give you variable sized strings and hit testing, but not a natural layout.
I think I would use RTB and make hit testing work with the MouseDown event and GetCharIndexFromPosition(), reading back the tag at the clicked location. You'll need a bit of logic to find the starting and ending white space around the word.

Resources