Assume i have a WPF diagramming application like this example:
https://www.codeproject.com/Articles/24681/WPF-Diagram-Designer-Part-4
How can I do an automated UI test for functions like:
Inserting a new item per drag and drop
Connecting 2 items
Deleting an item
I seen test libraries like "White" or "Appium" which is good for some text input but I have no glue how to do for example drag and drop of items in an automated test.
One diagram application is not like another diagram application. Even if WPF is used in both cases. What counts is the modeling of the items and connecting lines.
If the items are regular WPF controls then any test tool supporting replay (and maybe even recording) of actions like click, mouse press, release and drag will support automation of above actions. With statements like
dragAndDrop(source, sx, sy, target, tx, ty)
This assumes a reliable identification of the source and target objects. Do they have unique properties that tell one e.g. line element from the other?
If the Application Under Test renders the items on a canvas (like WPF Diagram Designer seems to do) then object-based access may be out of question. An image-based approach can be the only viable solution then. An equivalent of above dragAndDrop() call using an image-based testing:
var img = waitForImage("MyItem");
var x = img.x;
var y = img.y;
mousePress(x, y, MouseButton.LeftButton);
mouseMove(x, y);
mouseRelease(x,y, MouseButton.LeftButton);
Again, identification of primitive elements like lines can be challenging. In that case I would go for some scripting and query the application's internal model of the diagram structure and position of its elements.
Related
Background: I'm currently developing the client side for a web application, using JavaScript, with jQuery and Backbone.js (these are required by the proponent).
This is an application to visualize and edit data, in a graphical mode (through interactive diagrams representing the data, mainly).
Terminology: Said data is under the format of multiple documents, each containing a list of items.
For the purpose of this question, let the items be composed by an identifier, a textual description, and links to items in other documents. Links should be symmetric (i1 -> i2 exists if and only if i2 -> i1 also exists).
The Current Goal: In this phase, the application should be able to read two documents, display both lists side by side, and then draw lines, connecting the items between both documents, according to their links.
These lines should be editable. In other words, the user should be able to create new links, or remove existing ones (reflecting the changes on the item models).
These documents can be somewhat long, say, some dozens of items (maybe a few hundreds, in a realistic scenario). Of course, the page will be scrollable, to allow the user to see everything.
Also, for user convenience, there should be a slider to scale the view (allowing zoom in/out effects, so the user is given a global and a local view, being the latter more adequate for editing and the former for analysis).
Furthermore, the user should be allowed to hide particular items (useful when an item has many links, creating visual rubbish).
What I've managed to do:
Read data and map it to Backbone models and collections;
Display both documents side by side (Backbone views), with item connections;
Allow interactivity on these connections (drag-and-drop to create lines, click to remove), reflecting changes on Backbone models;
Hide particular items;
Scale effects.
I've achieved this using SVG, after coming across jsPlumb.
The Problem at Hands: The application still needs adjustments (emphasis on the scaling effects). Regardless, I found jsPlumb to be comfortable to work with. However, rendering performance seems to be a little lacking, when using the slider (it's possible that the slider steps are too small, thus firing too many events).
The proponent suggested that I try, instead, Sankey diagrams, to represent this kind of data. They also suggested that I try Sankey by tamc, based on Raphaƫl.js.
Of course, the visual factor is also contributive.
My question(s): Does this library have a good compatibility with Backbone? Possibly, if I use the resulting SVG elements as Backbone views' elements.
Also, does any of the two have a significant rendering performance advantage over the other?
On a final note, are there any other libraries more adequate to this scenario, worth the time of rewritting the application, that I might suggest to the proponents?
The project is going on, and I ended up using Sankey by tamc, with some extra work of my own, to better adapt it to this particular case.
I'm working on an app, that displayes huge (10000+ elements) graphs in a wpf canvas.
I'd like a feature like in Visual Studio, when you can split the view of an editor (so I can view two distant part of the same graph at the same time).
I have some constraints:
data binding (creating the bindings) of graph elements makes the loading of big graphs very slow, so I'm not using MVVM, the "VM" knows about the view and updates it directly when needed
the children of the canvas are frameworkelements, since I use the Tag property
because of the number of graph elements, I don't want to keep two different view for each element for the two part of the split view
So it should be like displaying multiple parts of the same canvas in different places. You can't set two parents for the FrameworkElements in WPF, so the easiest way is out of question :(
What are my options? Should I reconsider my constraints or there is some workaround for this?
Let me know if you need any more details (it's a big application, so I can't give you every information).
Edit: duplicating with visual brush is not an option since I need proper input event notifications, so both view must be editable.
Options:
Bind the same data to two controls.
Use a visual brush and duplicate input on the real control.
Create a custom graphing control that can output two parts of the graph at once.
If binding to two controls is too slow, then I think you need to rethink your application. The very fact that you have so much data displayed at once that you need a dual view to see separate parts is disturbing. That should raise a red flag. The red flag would notify you that, "What I need, and what I have is different." And you should go back to the drawing board and find out what you really need.
Otherwise, it might be best to create a custom control. The graph is rendering in its entirety even though you only need small portions displayed. If you had your own custom control you could speed up the entire app by rendering only visible portions at a time, and splitting within the control.
I have an old VB6 application. I want to recreate it in VB.Net using WPF. But I am a bit confused about the "Model View Controller"-pattern. I have two books about design patterns (GoF and J.Bishop) afair this pattern is indeed not mentioned inside one of the two books. I have also searched the internet I found some java-examples. But I have still no clue how I should use MVC-Pattern (should I?) in my new WPF-application.
Let's say for example my model (in fact it is more complex) is only a wheel rim (circle) with the properties Manufacturer, Diameter and Depth. The user should be able to modify the properties using textboxes and ComboBoxes.
Could somebody create a small example that explaines the MVC-Pattern with WPF?
Of course I like reusable classes to have a feasible concept throughout the whole application.
thanks in advance
Oops
Here's a "brief" description of what the MVC pattern is and how I would apply it to a WPF application.
(I might have a few details slightly off since I've mainy hacked in Silverlight but the concept is similar enough.)
Basically, the idea is to separate concerns and define interfaces between the different parts of an application, with the goal of keeping the code structured and maintainable.
The Model in your example would be pretty much exactly as you described the wheel rim - a WheelRim class with the various properties defined in suitable data types. I would put the model i an separate assembly to keep it apart from the other code, but you can settle for just keeping the model classes in a "Models" folder. The model would also have a "twin" in a database, the model classes being pretty much one-to-one-mapped to tables.
(You might wanna have a look at Linq2SQL or Entity Framework, if the database is defined you can pretty much get the model for free along with suitable database access code.)
The View would be the actual WPF xaml files - Defining the Grid or Canvas or what have you. On the WheelRimView there would be labels and textboxes for displaying or accessing the different properties, perhaps along with product images and the like. The code behind for the view would have all the relevant event handlers (start, button_click and so on) for getting the data from the fields and passing them to the controllers.
The Controller would be any "handler code" that you would use to manipulate the data. We're talking the basic CRUD operations here, along with validation and the like. Also, the controller layer would be responsible for compiling the data in a format that can go seamlessly into the View. The WheelRimController hence would have methods like "GetWheelRimList", "GetWheelRim", "AddWheelRim", "ModifyWheelRim" and "DeleteWheelRim". The methods take the values as in parameters and manipulate the model objects accordingliy. the
I would recommend keeping the code-behind of the xaml files free from any "controller"-ish code like validation, aggregation and the like - the code behind should basically only take the values from the textboxes, listboxes and such and send them on "as is" to the controller methods for processing. Also, you should keep any data formatting code to a minimum when getting data for presentation (i.e., no filtering or translating in the view).
A typical use case of "User opens a wheel rim and edits the diameter" would play out thus in code:
User clicks "Edit" on a list page. The WheelRimView page loads.
The WheelRimView.Load() method (or corresponding) calls WheelRimController.GetWheelRim(wheelRimId).
WheelRimController.GetWheelRim(wheelRimId) gets the corresonding data from a database table and populates the properties of a WheelRim object, which is returned to the WheelRimView.
The WheelRimView inserts the property values into the labels and textboxes.
The user changes the diameter value and clicks the "Save button.
The WheelRimView.Save() method calls the WheelRimController.ModifyWheelRimDiameter(wheelRimId, diameter) method.
The WheelRimController.ModifyWheelRimDiameter(wheelRimId, diameter) method parses the diameter (if it is a string) and loads the model object. It applies the modified value to the model object and saves it into the database.
The WheelRimController.ModifyWheelRimDiameter(wheelRimId, diameter) returns a status code to the WheelRimView (for instance a predefined numeric stating any validation errors) to report the success of the save.
The WheelRimView displays a result message (hopfully "saved") to the user.
I hope that clears a few bits up.
Bevcause of the rich binding support available, WPF (and Silverlight) are well suited to MVVM (Model-View-ViewModel). MVVM is an extension of MVC that uses a view model to bind the current state of a view, instead of manipulating the view directly.
There are a bunch of MVVM frameworks available, as well as Microsoft's own Prism framework (which is arguably more useful if you have a larger, modular application).
WPF is probably more well suited to MVVM (Model-View-ViewModel). I'd recommend reading this MSDN article on MVVM and, perhaps, following their advice. There's also a nice collection of links I found on the Bryant Likes blog.
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.
My company's product is, at its core, a framework for developing metadata-driven UIs. I don't know how to characterize it less succinctly than that, and hope I won't need to for purposes of this question, but we'll see.
I've been trying to come up to speed on WPF, and have been building UI prototypes here and there, and recently I decided to see if I could use Expression Blend to help with the design of these UIs. And I'm pretty mystified at this point.
It appears to me as though Expresssion Blend is designed with the expectation that you already know all of the objects that are going to be present in the UI at design time. But our program generates these object dynamically at runtime.
For instance, a data row might be presented in a horizontal StackPanel containing alternating TextBlocks (for captions) and TextBoxes (for data fields). The number of these objects depends on metadata about the number of columns in the data row. I can, pretty readily, write code that runs through a metadata record and populates a StackPanel dynamically, setting up the binding of all of the controls to properties in either the data or metadata. (A TextBox's Width might be bound to metadata, while its Text is bound to data.)
But I can't even begin to figure out how to do something like this in Expression Blend. I can manually create all these controls, so that I have a set of controls that I can apply styles to and work out the visual design of the app, but it's really a pain to do this.
I can write code that goes through my data model and emits XAML for all these controls, I suppose, and then copy and paste it. But I'm going to feel really stupid if it turns out there a way to do this sort of thing in Expression Blend and I've dropped back and punted because I'm too dim to figure out the right way to think of it.
Is this enough information for someone to try formulating an answer?
I think expression blend is a very good choice ESPECIALLY if you want to design dynamic, datadriven UIs. You can use Blend to desgin DataTemplates that define how a single dataobject is to be presented to the screen. For example, if you have an object of type Person you can define the controls like textboxes, border etc. that then are to be generated automatically for each Person in your list.
You can then fill your ItemsControls (DataGrid, ListView, TreeView ...) with those dynamic databojects and WPF knows how to render them. If a Persopn is removed form the list, the generated visual item will be removed too. This is just a simple example the whole notion of dynamic data is deeply baked into WPF and you can access these features using blend.
To be able to design the datatemplates in expression blend you need to provide sample designtime data.
Also to be effective with all this it is of high advantage if you stick with the MVVM design.