Cef Browser Wpf explore the dom, find elements and change values - wpf

Further to a post (CefSharp load a page with browser login).
I implemented the IRequestHandler interface and the different methods, particularly the GetAuthCredentials where I show a dialog and recover user and password and passing it to the event handler.
Now I want to access to the dom where I get several frameset with differents frames and I'm interested in one frame which I know the name Atribute.
Inside this frame I need to get list of different type of input , select etc...
In my app I have a button which I use to set values of the different elements depending if they are present on the displayed page.
PROBLEM is I don't see any way of getting the document, the frames collection etc....

CefSharp doesn't expose the underlying DOM, and is unlikely to see http://magpcss.org/ceforum/viewtopic.php?f=6&t=10652&p=19533#p16750
Your best bet is to use EvaluateScriptAsync and a combination of Javascript Binding
https://github.com/cefsharp/CefSharp/wiki/Frequently-asked-questions#2-how-do-you-call-a-javascript-method-that-return-a-result
https://github.com/cefsharp/CefSharp/wiki/Frequently-asked-questions#3-how-do-you-expose-a-net-class-to-javascript
If you absolutely must have DOM access and cannot invent your way to a solution then CefGlue might be a better choice for you. (I should point out that the DOM can only be accesses in the Render process, and as such calls needed to be passed to the Browser process though IPC, so it isn't a trivial task).

Related

Best practice passing Linq2Sql between WPF-Forms (Windows)

I often have the situation that I need to pass a linq2sql object from one WPF window to another one.
For example I have a window with a list of linq2SQL objects. The list is bound from a public declared DataContext in the "Window_Loaded"-event. With a double click on one of these items a second window opens and the object can be edited. While opening the selected object is passed to a property of the second window. After the user has made some changes he decides to discard the changes and closes the second window.
Now because the input fields are bound directly to the Linq2SQL object the changed values are still present.
What is the best practice in this situation? Is it better to pass a newly created object from a new created DataContext to the second window? Then I have to somehow refresh the list on the first window when the changes are wanted.
Or can I use the already bound object from the list of objects from the first window and pass it directly to the second window?
I know that I can refresh the object when I have to reload the object
DB.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, MyObject);
What is the best practice?
The question is more general and touches the important issue: what lifetime policy best suits the linq2sql datacontext in different types of applications.
In case of a web application, this question has a simple answer: the "per-httprequest" lifetime policy is the most convenient.
In your case, a WPF application, there are two approaches I am aware of:
in a "per-the-lifetime-of-the-application" policy you would create a single data context for the lifetime of your application. Although technically this works, there are potential issues with the memory consumption - as the application retrieves more and more data, the first level cache in the data context grows without control and could possibly just run out of resources at some point
in a "per-presenter (view)" policy you create a new data context in each of your presenter (view model) (or view, if you don't follow mvvm) which means that two different views do not share the same context. I'd say this is recommended approach, there are no risks of unwanted resource issues, however, you need an additional mechanism to pass events between views so that views could be refreshed when the data changes.
Note, that all your business logic should be unaware of the actual policy. To do so, let your data context be injected (by constructor for example) to any class that uses it. Depending on the actual policy, a proper context is injected into a business class. This way, you could even change the lifetime management policy someday with no need to refactor your business code.

Should I use a central event bus with backbone.js?

I am currently working on my first backbone.js app. The concept of events is quite familiar to me but I am in question if I should use a central event dispatcher or not. Generally I see these two approaches:
Directly wire event publishers and event receivers together. (I started with this approach.)
Use an event bus and wire publishers and receivers to this bus.
Is it favorable to use an event bus in terms of e. g. long time maintainability of the app and traceability of events?
Whether to use a central event bus or to directly wire events together should be assessed on a case by case basis. Depending on the circumstance, there are times where you will favour one over the other.
I will use a central event bus whenever I can due to the fact that the publisher and receiver are not tightly coupled. In my opinion, this makes your code more maintainable and flexible.
I find central event buses very useful when you have:
A single event publishing instance and numerous event receivers.
Many event publishing instances and a single event receiver
The benefits of the central event bus in the above cases becomes even more apparent when the event receiver instances or publisher instances are dynamic and thus being created and destroyed over the life of the Application. As an example, consider the following single page app:
The single page app must stretch to fit the browser window width.
The single page app is primarily a tabbed set of views, however the number of tabs is dynamic as they are created and destroyed by users
The contents of the tabs are all different with the exception that they have a main area of content that must be stretched to fit the available width after accounting for the width of other sibling elements
Resizing needs to occur at many different points due to the contents of tabs continually changing.
In the above case, regardless of the specific scenario, the central bus model works really well. A code example would be:
Application Level
var App = {
init: function () {
// Event to resize width of element to remaining width
App.Events.on("fitRemainingWidth:app", this.fitRemainingWidth);
},
// event pub sub for the app.
Events: _.extend({}, Backbone.Events),
// function that expands an element, or elements to the remaining width in the window.
fitRemainingWidth: function(targetEls) {
var els = $(targetEls);
_.each(els, function (e) {
var el = $(e);
var cont = el.parent();
newWidth = cont.innerWidth();
otherElements = cont.children().not(el);
otherElementsWidth = 0;
otherElements.each(function () {
otherElementsWidth += $(this).outerWidth();
});
el.width(newWidth - otherElementsWidth);
});
}
}
In your views
Whenever a something needs to be resized, you trigger the event, for example:
App.Events.trigger("fitRemainingWidth:app", this.$(".main-content"), this);
As you can see, this is really useful, because the fitRemainingWidth function can apply to anything at all and you never know which views may want to use it in the future or when it will need to be called.
So I guess I should move onto when I find not using a central event bus preferable. I am sure there are other cases, however the main one for me is when the receiver needs to be wired to a specific instance of the publisher. For example, if we continue on with the tabbed application example, lets say that the contents of each tab is a split view of a particular person's mailbox. In each split view is a list pane showing a collection of emails and a reading pane showing the content of the currently selected message in the list.
In this case we want to trigger a "selected:email" event when an email is clicked and have the appropriate reading pane bound to it so it can display the email's contents.
Say we have ten mailbox tabs open, each with their own email list pane and reading pane. That makes ten email lists and ten reading panes. If I was to use a central event bus for this scenario when I triggered a "selected:email" from one of the lists, the reading panes that are receiving these events from the event bus would need to have their own smarts to try and work out whether the selected email was something they need to display or not. It's not really desirable for each reading pane to try and work this out and there is uneccesary logic involved. Its far better for a reading pane to just receive a "selected:email" event with the email object as it's payload and just display it.
So in this scenario, its better to to make each mailbox tab view responsible for wiring the events of it's specific child view instances and their models and collections. In our example this means a specific instance of an email list view with it's collection and a specific associated instance of a reading pane view.
In summary, I am suggesting there are use cases for each and that you should try to be judicious on choosing the right approach for each circumstance that you come across. Use both and learn to see what fits in which circumstances.
Lastly, in regards to the traceability of events, you can always write a wrapper for the On and Off functions in your event bus that both calls the normal On and Off functions but also adds/removes information to a register containing which objects are bound to which events. You could use this for debugging and write to the console information about these objects so you can have a clear picture of the state of your event bus and its listeners at any point in time. I've not ever thought about doing this, but there is no reason why you couldn't ;)
Post Edit: The comment by tsiki regarding using Local Event buses is a good one. In the above example I made with many tabbed mailboxes, you could use a local event bus for each user mailbox tab view. You might want to do this if each mailbox tab view became quite complicated in its own right containing many nested child views and large amounts of events to be generated/handled.

Adding controls to winform while allowing user to enter input

I have a WinForms data entry form that will have upwards of 1500 questions. I have the questions broken into sections, and each section will have an unkown number of questions. Each section is its own user control and has rows (2 panels, 2 labels, a textbox, and another user control) created and added dynamically for each question. The section controls are then added to the form.
My problem is that the process takes a lot of time, even with using TPL (Task Parallel Library). I would ultimately like to create/add the controls and allow the user to start entering data at the same time. The controls are going into a scrollable panel. While the user is entering data, that data will need processed on a local database...so more threading could be necessary.
I have tried working with TPL, which I am new to, by having all the controls added to a list during processing and then sorted and added to the form after the Parallel.ForEach was complete...takes about 20 seconds for over 1200 questions.
I also tried utilizing a BackgroundWorker component. Using the BWC seems to be the faster of the two, but there is a race condition for the ProgressChanged() eventhandler and not all controls get added...not to mention the way the form looks with all the rerendering.
Am i just using TPL wrong? What's the best way to go about this? Is there another way or do I just make the user stick out the wait?
Thanks
Am i just using TPL wrong? What's the best way to go about this? Is there another way or do I just make the user stick out the wait?
Most likely, you can use TPL, and get the same response time as BW, but a nicer API for this type of operation.
The trick here is to get a TaskScheduler setup for UI interaction, and then use the Task class to push the controls back onto the UI thread as they're ready. I have a blog post on this specific subject which shows how to get a TaskScheduler setup to use with UI threads.
However, I would recommend keeping these in memory and pushing them in batches, to avoid constantly re-rendering the UI. This is likely to be an issue no matter what you're doing.
That being said - I'd question your overall visual design here - if you're trying to display over 1200 questions to the user, some form of paging is probably a much nicer approach than a huge scrollable container. If you page these, you could load and process the first few (which is probably near instantaneous, since you mentioned you can process about 50 questions/second), and then continue loading the others after the first few questions have been displayed.

Silverlight Binding in Pivot Control

I have a design question : In a pivot view (three "pages"), I have a lot of bindings. Well, about 12 items in each pivot view (TextBox, Map...).
I realized that these binding were slowing a lot the load of my view. But the binding on the first "page" of my pivot is the only one that needs to be loaded. I can put a progress indicator and load in a thread or something my other data (in fact, the binded data will be set only after an HTTPWebRequest).
How can I tell that to my application ? Like "onLoadPageX: bind items"
Thanks a lot, I don't know if i'm clear
You should be able to add a RoutedEventHandler for the Loaded event of each PivotItem. This event is fired when a particular PivotItem page is loaded; there is also a corresponding Unloaded event for when the page unloads, in case you need to free any resources.
Your question is quite vague but there are lots of options around showing a loading state, defering binding and having lots of controls in a pivot:
If you need to do anything that may take time then do it off the UI thread.
If you're doing something which takes time then you should show an indication to the user that something is happening. This could be a message or animation, depending on the likley time period and the rest of the application.
If your content is highly dependent upon data loaded from the web, be sure to have appropriate timeouts on failing to load the data. Also have useful messages if there is no data connection available.
If your UI is highly dependent on details loaded externally you could look at adding the controls to the UI once you know what you need to display.
If the UI will always have the same controls but different content in them, you could consider data-binding to objects which have placeholder content which is updated when the relevant information is downloaded from the web service.
If you have lots of items in your pivot you should consider defereing the loading of individual items so that you don't load them before they are needed. Only load the data on the items next to the one displayed. This way they appear preloaded to the user but ease the impact on the system.

Need to get back form controls' information externally

Are there any tutorials or guides out there that anyone knows of that will show me how to read forms from an external program and get back information about the controls on the form? Currently, I can get the handle to the form, and I can get the class name, but I need to get more information such as a persistent name and contained data. Thanks.
Edit:
I now have a way to read the contained data (with the WM_GETTEXT message), however, I still need a persistent name/ID that I can be sure will not change from instance to instance. One way I can think of for doing this is to take the handle, find the position of the control on the window, and then get the handle from the position from then on. Another way is to determine a static ID for the control and then use that to get the handle from then on. The new scope of my problem is how to implement either of these. Any Ideas?
I would look at UI Automation; in particular, the RuntimeID property, the NativeWindowHandle property, and the Name property.

Resources