Bookmarking WPF's FlowDocumentReader - wpf

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();

Related

Ext.js 4.x Dock-able window as tab

Has anyone seen an implementation or plugin for extjs where you can "pull off" or "dock" tabs/windows the way you can with a browser? Is it even possible?
Searching has not revealed much but I did come across a proposed solution in an older version:
http://www.sencha.com/forum/showthread.php?16842-Dockable-floatable-panels-in-ExtJS
#DmitryB
To clarify, in chrome if I have multiple tabs in the same window like so:
And I "drag" one of the tabs, it pops off into a new window:
I imagine you might accomplish this by moving the content of the tab panel into a window but not sure how to go about it.
In a nutshell:
- Make the tabs draggable, watch for the drag event and mark the
tab-strip as your "safe" zone
- When a tab is dragged and then "dropped" (as in, the drag event ends) you do a check:
> Is the tab within the safe area?
No: Create a new Ext.Window at the x/y of the mouse, copy the components/HTML
out of the original panel and insert them into the new window. Destroy the
original panel.
Yes: Do nothing.
Unfortunately, I am still quite jaded from learning D&D in ExtJS3, so I can't offer any help with this and real code pertaining to ExtJS 4, however the concept seems relatively straightforward to me. I would say you're going to probably want to do your best to NOT have this be flashy - unless you REALLY REALLY need to, I wouldn't worry about showing the panel's contents while you drag the tab - much less show the panel itself. Just let the tab element get dragged around the screen and copy when it's released outside of the safe zone.

MS Word pagination using Multiple wpf RichTextBox

My aim is to make a editor behave similar to MS-Word.Wpf RichTextBox is a wonderful control for it.By placing it inside a ScrollViewer,we can make it editable.(Like a notepad).But I need MS-Word like pages.One effective way probably is to apply style to scrollViewer such that we create a look and feel of multiple pages on richtextbox but I dont know how to do it.What we are doing in the project is to use a documentViewer. Inside a FixedPage,create a Header(Canvas),Body(WpfRichTextBox),Footer(Canvas). And thus create multiple pages,and by subscribing to RichTextBox sizechanged event, we are manually doing the pagination i.e move the blocks from one page to another when height has changed. Do you see any better approach in doing this? Does using multiple richtextboxes hamper my performance?
#WpfProgrammer This is the good approach I would say. Say if you have 1000s of pages then, there will definitely be a performance problem. For avoiding that problem, you need to do demand paging.
Virtual Paging :
1. You need to construct a page table, which will contains pages. Each page will contains information about the controls, images, their positions, dimension and Styles for the page. [All serializable data]
2. Virtual Pages - You need to
de-serialize all the data for the
page and create a page with
RichTextBox. Virtual Pages are
nothing but, pre-cached pages that
are going to be rendered. Say for
example. If I'm in 1st page. Then,
I'll de-seriealize next 3
consecutive pages and have them in a
collection. Then, repeat this
procedure for consecutive page
movements. Adding some logic using
Most Frequently Used collection. It
will be fast enough. In the case of
1000's of pages. You can collapse
those non-dirty or never visited
pages. That could yield little more
performance. If performance is far
more concern for low hardwares.
Then, you should consider
cleaning.
3. Cleaning -
Cleaning is the process of
identifying LFU pages and remove
them. This would be very helpful if
performance is more pronounced.
Hi Tameem
Set the min height,width of the richTextBox to A4 size(lets say). Subscribe to RichTextBox Size Changed event.As soon as the content exceeds,this event gets fired.Then I take the last block of previous page and push it to the first block of next page.(Remember if page doesnot exist, you need to create new page then add it as first block).And also the focus should be changed to the new page.(because if you press enter at the last RTB, you expect the focus to be there in the new page.).When the user deletes a block in some page(say 2nd),then you need to add all the blocks of bottom pages to this page,so that our pagination logic will push the blocks down again and adjust. I can share some piece of code if you need further help.

Complex .Net 2.0 Windows Forms control: where to start?

In order to make a convenient UI for an .Net 2.0 Winforms application I am working on, I have need for a control that I'm pretty sure goes beyond the "out of the box" behavior of any standard control. A mock-up of what I'm trying to achieve follows:
Mock up http://www.claware.com/images/temp/mockup.png
Essentially, this part of the application attempts to parse words into syllables from tribal languages (no dictionary to refer to; any and all unicode characters are possible.) By the time the user gets this far, he has already defined the vowels / consonants in his language and some other configuration. There is then an iterative process of (1) the application guesses which syllables exist in the language based on some rules, (2) the user refines the guesses, selecting the correct parsings or manually parsing a word, (3) the application "learns" from the user's feedback and makes smarter guesses, (4) repeat until the data is "good enough" to move on.
The control needs to present each word (the grey headers), then all the syllable break guesses (the white areas with dots separating the parts of words.) There is also a way to manually enter a parsing, which will display a text area and save button (at the bottom of the mockup.) When the user hovers over a guess, the background changes and "accept / reject" buttons appear. Clicking on the accept, or entering a manual parsing, removes the entire word from the list. Clicking the reject button removes just that item.
I'm by no means 100% sold on the formatting I have above, but I think you can get a general idea of the types of formatting and functional control I need. The control will also scroll vertically--there may be thousands of words initially.
My question for you experienced WinForms developers is: where to start? I would really, really like to stay within the .Net core framework and extend an existing control as opposed to a third-party control. (At the risk of starting a religious war: yes, I suffer from NIH-syndrome, but it's a conscious decision based on a lot of quick-fix solutions but long-term problems with 3rd party controls.) Where can I get the most "bang for my bucK" and the least reinventing the wheel? ListView? ListBox? ScrollableControl? Do I need to go all the way back to Control and paint everything manually? I appreciate any help that could be provided!
[Edit] Thanks everyone for the ideas. It seems like the most elegant solution for my purposes is to create a custom control consisting of a FlowLayoutPanel and a VScrollBar. The FlowLayoutPanel can contain instances of the custom controls used for each word. But the FlowLayoutPanel is virtual, i.e. it only contains those instances which are visible (and some "just out of scroll"). The VScrollBar events determine what needs to be loaded. A bit of code to write, but isn't too bad and seems to work well.
I would look at the TableLayoutPanel and FlowLayoutPanel controls. These will let you organize a series of controls with moderate ease in a vertical fashion. I would then create a UserControl that consists of a label and 2 buttons. The UserControl will expose properties like Text and events that are exposed for the button clicks.. For each entry in the list, you will create an instance of the UserControl, assign the text value, and handle the click events. The instance will be placed in the Table/Flow panel in the correct order. Both of those layout panels do allow for inserting items between other items so you can add/remove items from the list dynamically.
Edit:
Given the length of what you are trying to render, I would consider using the DataGridView and do some custom rendering to make it perform how you want it to work. Using the rendering events of the DGV you can merge columns, change background colors (like highlighting the dark gray lines), turn on/off the buttons, and handle changing the grid into edit mode for your rows to allow modification or inserting of new values. This method would easily handle large datasets and you could bind directly to them very easily.
Well, this certainly looks like a candidate for a custom component that you should be creating yourself. You can create this using standard .Net drawing commands along with a text-box, and a regular button control.
Now you want to find out where to start.
Create a Windows Forms Control Library project.
Drop in the textbox and the button control.
The panel drawing code should preferably be done by code. This can be done using the regular GDI+ commands.
Edit:
Here's another idea, and one that I've practically used in my own project with great success.
You could use a web-browser control in the app, and show your data as html. You could update the source of the web-browser control based on the input in the textbox, and clicking on the links in the web browser control will give you the event that you can trap to do some action. Your CSS will work.
I used this technique to build the 'desktop' in an app I made called 'Correct Accounting Software'. People loved the desktop so much that it is one of the best loved features of the app.
Here's how I would do it:
Create a custom control. In this custom control, have a ListBox atop a LinkButton, and when the LinkButton is clicked you can make it give way to a TextBox. The ListBoxes will have the top row unselectable... you can probably get the rest from there. When you get your list of words, fill a Scrollable of some kind with one control for each word:
(foreach String word in words){
myScrollable.add(new MyComponent(word));
}
From there, I'm not sure what you want to do with the boxes or the data, but that's my initial idea on the UI setup.
Use the WebBrowser control and generate the HTML markup into it using DocumentStream or DocumentText.

How do you switch between "pages" of a Silverlight application?

I am currently loading the default file, page.xaml, but in that page, I am loading the content from another xaml file. With each "page" change, I just load the content from a different xaml file, and on and on.
Example: this.Content = new StartPage();
I'm running into some syntax issues, however, because of the way I am changing my content, and was wondering if there is a definitive answer on how to accomplish this?
For example, when trying to capture user's keystrokes, I would normally do:
this.Keydown += new KeyEventHandler(this_KeyDown);
but that event handler doesn't even fire in my situation. So, I'm looking for a new approach to my content-switching approach before revisiting the keystroke problem.
Have you looked at using Silverlight 3. It has a new Page Navigation functionality.Silverlight 3 Navigation
As far as content switching goes, I've always done what you propose in the question. Normally I create a MainPage.xaml which has has the frame of the application (usually a Grid for me). One of the cells in the Grid is considered the content area of the app. When the user takes an action that I would consider to be navigation, I create a new instance of a Page, which for me is a file like MyUserControl.xaml, and then add it to the appropriate content cell in the Grid. MainPage stays around for the life of the application and assists with navigation.
If you want something fancier, and want to take advantage of browser based back/forward buttons, you could look into the SL3 navigation like Correl suggested.
A Big problem with what your're doing is that journalization doesnt take place automatically when you swap out framework elements by creating them and plugging them in the codebehind. This means that you lose the back and forward functionality of the browser. You can manually journalize stuff when you swap out pages, but this is simply a hack to get your navigation approach working.
Take a look at Prism at www.compositewpf.codeplex.com/, specifically the MVVM method of GUI design, it'll save you alot of time later on. And remember, you dont need to go hardcore when you look at MVVM, u could always cut out alot of "dynamic" functionality if you're a one man band
Also swap to silverlight 3 and use the navigation application. If you cant, take a look at helix 0.3, it'll provide a more asp oriented approach to navigation. the link provides a really really good starting point, its a three part article, i suggest you read all three and download the sample application and understand it.
A book could have been written on your question, this has to suffice for now.

Best way to show screens to user on application

I'm developing a Winforms application which has been running for years with an explorer view (TreeView left, screen right). I means that:
All the screens have an hierarchy organization
All the nodes on TreeView have one and only one screen related.
A screen gets activated when a node on treeview gets selected.
One of the advantages is that the user has an ordered stucture and one of the inconveniencies is that with hundreds of screens the user gets confused.
I see other options: use classical menus, use tabs or a mix of everything.
Any advice for a good way to show a lot of screens to user in a user-friendly way?
Update: I'm changed "hundreds screens" by "a lot of screens". The most important thing is not show all at time but that the user can find what they need easily.
Update2: In this proposal, the user only see one screen at time.
Update3: I'm talking about handling multiple screens not showing multiple screens. No MDI, only one ontime.
I have used other applications similar to this is the past, and the major problem is trying to find the exact screen you want. There are two common solutions to this problem, shortcut codes and favorites menu.
With the shortcut codes, allocate a short code (5 or 6 characters) to each screen. The user then inputs this shortcut code into a text box which will then jump to the correct screen. Users will create their own list of often used codes.
For the favorites menu, allow users the ability to be able to create their own menu list in the structure they want. They will find things easier, if they organize it themselves.
Why do you need to show so many seprate screens at once? Why not just show the screen for the currnetly selected node, why are all needed at once?
If it is all tabular data is is probably too much to be consumed all at once, if it is graphical data, could it not be combined?
There may be a valid reason to show all the data at once or there may not, hard to tell from what is provided in your question. With that said, better to keep it simple than overload the user. MDI apps are never easy to use.
Tabs may work for a small set of items but still is not a good UI for hundreds of items.
If you are only showing one element at a time, out of hundreds possible on the tree nodes, then that is fine. The one screen showing at a time would be contextual to the item selected as the user moves through the nodes. Think of the Outlook approach where what is selected in the left pane is displayed in the right pane in whatever form fits the data being displayed.
Have you considered the Office Ribbon?
The Ribbon gives you a lot of flexibility on how to show and
organize functions and it's highly visual.
Here is a good link about the Ribbon and also here
To use the Ribbon you have to license it from Microsoft. You can do that online.
Providing the user with ketboard shotcuts is usually a good thing too.
I also like to provide the user with an "autocomplete" field on the menu
so that they can can find the function by name (or part of it) and be
able to navigate directly to where they want to go.
I general I find trees to be a bad idea, especially if your "hierarchy" is of a small fixed depth.
If you have a small fixed depth, consider replacing the tree with a list. At the top of the list can be drop-downs for filtering based on the node-level properties. It will use up less screen real-estate because it is vertical-only, with no horizontal component.
Clicking on an item can display it in the view (like currently), but it may be a good idea to allow a user to double-click on more than one item which could launch more windows, or tile with the existing displayed items. (I am assuming that currently, the user only sees a single detailed view at once in any given window.)
Actually, it’s hard to beat a hierarchy for organizing large numbers of items. I wouldn’t favor a classical pulldown menu for vast numbers of windows because it would be even harder to keep track of where you are than in a tree (e.g., a tree lets you look in multiple branches at once). But here’s a few alternatives:
I’m not clear how you ended up with so many windows, but maybe it comes from combinations of classes, views, content, and detail, or maybe it comes from using a task-centered UI structure for something far too complex (I’ve more on that at http://www.zuschlogin.com/?p=3). For complex apps, you want a different primary window for each significant class of data object (e.g., invoices, employees). These are listed on one menu, and typically there’s few enough (15 or less) that it can be single non-cascading pulldown menu. The content of each window is set by a separate menu, perhaps by a menu item that opens a dialog that may include a list box (like an Open dialog) or other controls for querying/searching. The “view” of each window (how the data objects are shown, e.g., table versus form) is set by menu items in the View menu. Details for any given object in a window can be shown in a separate pane within the window in a master-detail relation, essentially turning you data objects into a menu for details. A single window can have multiple detail panes for the user to open and close to select the specific detail to show. Tabs may also be used within a single pane to fit subdivisions of content.
You say it’s not important to show all window options at once, but often showing all options at once makes it easiest for users to find what they need. Maybe you need a “home” window that lists all the other windows in organized, labeled, and separated categories. This is will be easier to use than the tree if your users select a window then stick with it for most of the session. Your tree is better if there's frequently selection of windows throughout the session, owing to the overhead of getting to the home window. If all windows/options don’t fit on a single home window, then show only selected common windows for each category on the home window and provide a button or link to show an exhaustive list.
If you’re talking 100’s of windows, maybe you should have Search, perhaps in addition to a menu-based browse approach to getting to a window.
In any case, providing easy access to the few most commonly used windows is a good idea. Such windows can be explicitly selected by the designer, based on user research, or selected by the the user (favorites), but it also typically works well to make it automatic with an algorithm that uses some combination of frequency and recency of use.

Resources