I am building a new bot in Automation Anywhere 11 and I have found recently a tricky situation when I'm trying to automate the Windows Ribbon.
If I have only one tab everything works as expected and I can identify all buttons inside, but if I have multiple tabs only the last tab elements are visible to the Object Cloning option, I have added unique Names, AutomationIDs, etc. And nothing has worked. This is a preview of the issue:
This is my example XAML code:
<UserControl x:Class="Example.RibbonMenu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
xmlns:my="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon">
<my:Ribbon x:Name="R1" AutomationProperties.AutomationId="R1ID">
<my:RibbonTab Header="Tab 1" x:Name="Tab1" AutomationProperties.AutomationId="Tab1ID">
<my:RibbonGroup x:Name="GB1" AutomationProperties.AutomationId="RG1ID">
<my:RibbonButton Label="Button 1" x:Name="RB1" AutomationProperties.AutomationId="RB1ID" />
</my:RibbonGroup>
</my:RibbonTab>
<my:RibbonTab Header="Tab 2" x:Name="Tab2" AutomationProperties.AutomationId="Tab2ID">
<my:RibbonGroup x:Name="RG2" AutomationProperties.AutomationId="RG2ID">
<my:RibbonButton Label="Button 2" x:Name="RB2" AutomationProperties.AutomationId="RB2ID" />
<my:RibbonButton Label="Button 3" x:Name="RB3" AutomationProperties.AutomationId="RB3ID" />
</my:RibbonGroup>
</my:RibbonTab>
</my:Ribbon>
</UserControl>
Also, I have read multiple options:
UI Automation and Ribbon control
XAML - Binding row and column index of cell to automation ID
Unable to generate Automation ID for WPF Controls, to be used by coded UI for automation testing
How can I find WPF controls by name or type?
Coded Ui test unable to find the WPF Ribbon button
How can i automate Ribbon UI
But nothing that I tried so far was worked until recently, I identified that the issue is connected to the last tab. Also, as I said in the comments section, I tried the Legacy Option and Manage Windows Controls too. Here are some previews:
Legacy Option Enabled:
Manage Windows Controls:
Furthermore, another ribboned app like Paint where the buttons are recognized:
Also, I have tested another Microsoft tool: AccExplorer32.exe, which shows exactly the same behavior, proving that this is not a limitation of AA or UiPath, but something from the coding perspective, here you have a preview:
Does anyone have an idea how to fix it? Or has experienced something similar? Thanks for your help.
P.S.
I'd not want an answer about Image Recognition or MetaBots (partial solution and quite good in the case of AA) as options since this is a programming issue and I'm interested to solve it.
I identified a second problem regarding the TabControl. If for any reason when you have only one TabItem active and you decide to hide the tab name for aesthetic reasons, my advice is to enable it for robots since if you hide it then the robot cannot find any elements inside and you might need a MetaBot, which wouldn't be as reliable as you want to.
Not working:
The tabs don't work even with MetaBots:
Working:
Also, I was able to find an example with Window Forms, Windows SDK and the regular ribbon from MS where it works as expected since the first time without any specific adjustment.
This is a partial solution if we cannot find a solution in WPF (I highly doubt, there is no possibility). Someone suggested I use a MetaBot, which is capable of screening the entire window, and yes, in this way, you're able to identify all controls that are visible (not in all tools, i.e., SAP without SAP scripting enabled, it's impossible).
However, I wouldn't recommend it since this won't solve major issues or bring stability in future changes or drastic ones from the screen or UI.
Also, I can suppose based on my experience that is going to be less efficient since in the "regular process" you are going to access a specific AutomationID of a unique control based on Object Cloning while in the MetaBot, you're going to constantly access the full screen to get all controls and later choose one by one using the logic you created and you will need to repeat the same actions each time for each screen and follow the same pattern for each action. Further, why do I think it's less efficient, you might ask because you're adding complexity to the solution.
If I find a better answer or solution, I'm going to add it as soon as I have it.
P.S.
It doesn't work for A2019. AA removed support for MetaBots and there is no current alternative besides image recognition.
For the time being, this is the only solution since neither Microsoft (they tried to silence me moving my question to the Off-Topic section and didn't reply my comment to move it back to the correct forum) nor AA (I had longs talks with them and they didn't want to take any responsibility or raise the ticket to MS for support) wants to help.
It's important to highlight that it's not necessary a reliable solution since the next version of Automation Anywhere v2019 it's a totally different tool based on different technologies that might not support everything "in the beginning" and could collapse all your robots and could lead to re-write your robots from scratch (I talked about this since they don't have proper migration tools).
Related
I'm trying to use OxyPlot to visualize a time series and I'm using annontations to mark some points in time and value levels like minimum/maximum value and so on.
I want to achieve this in WPF with bindings and, so far, I started with the Plot control, two axes and a data series. This works fine, but I can't find a way to bind the annotations to an ObservableCollection<Annontation> with dynamically created annotations of all kinds.
<UserControl
...
xmlns:oxy="http://oxyplot.org/wpf"
...
>
<Grid>
...
<oxy:Plot>
<oxy:Plot.Axes>
<oxy:DateTimeAxis ... />
<oxy:LinearAxis ... />
</oxy:Plot.Axes>
<oxy:Plot.Series>
<oxy:StairStepSeries ... />
</oxy:Plot.Series>
<oxy:Plot.Annotations>
<!--
How do I bind to the ObservableCollection 'Annotations' in my ViewModel?
Note, 'Annotations' property isn't available directly in Plot, either.
-->
</oxy:Plot.Annotations>
</oxy:Plot>
</Grid>
</UserControl>
I run in a similar question. Just to provide an answer for others, how to handle this with OxyPlot:
If you have an unknown number of Annotations or Series, you should use
<oxy:PlotView Model="{Binding PlotModel}" />
in Xaml and this Property on your ViewModel
public PlotModel PlotModel { get; set; }
On this property you have more flexibility. You can not set PlotModel.Annotations, like the LineSeries.ItemSource, but you can add and remove everey time so much annotations how you need.
After nearly a year without an answer I decided to answer with a short roundup of my experience from trial-and-error during that time.
I basically gave up the approach with OxyPlot in my WPF-application, so if the reader is rather interested in a solution with OxyPlot, (s)he will probably not find an answer, here, sorry.
After googling and the already mentioned trial-and-error etc. I finally switched to a solution with a web based visualization (Grafana in my case) and a time series database (InfluxDB in my case). There are other possibilities for visualization and data sources etc., but for my case this was the most appropriate. I won't provide a comprehensive list, so please google for alternatives for this.
The most interesting thing for my .Net-case was that I could embed a part of my Grafana graphs in a web component on my WPF window, but I didn't end up using this solution, so I unfortunately can't give a comprehensive solution any more. The important thing was, I could use Grafana in .Net via web-stuff, so no further limitation.
Meanwhile I dived more into the systems mentioned above and could build some very useful dashboards for our case and very quickly build some interesting queries etc.. Even if you want to create your own visualization, I would recommend to set up a virtual machine with a visualization platform, a time series database (or any other database system) and some services/daemons/scripts running somewhere. That helped me a lot.
If someone likes to add something, please feel free. At least for my case this question is answered, so I'll close it.
I have been tasked to design a contact management program for my company. We have VS 2012 and since I have never used WPF before I thought I would use it to develop this application.
I am having huge problem getting started on the binding when utilizing the entity framework for the database which btw is database first.
I have followed the instructions within this link to the letter.
http://msdn.microsoft.com/en-us/data/jj574514.aspx
The objects show up in the data sources window just fine. But when I drag and drop to my window, nothing happens. No idea what I am doing wrong and cannot find anyone else with this problem.
Can anyone help me out here? I have looked everywhere. Any help is appreciated
Ok. I actually went thru that article, just to show good faith and let you know that I actually want to help you.
I came to the following conclusions:
That article show a very basic scenario of getting data from an Entity Framework context and showing it in a WPF DataGrid.
It doesn't have any kind of validation nor business rules.
It doesn't have any UI behavior such as conditionally enabling/disabling or showing/hiding any UI elements.
That kind of scenario is where the Designer is useful, when you don't actually need anything except getting / saving data from / to a DB.
Unfortunately (or fortunately for all of us developers who make a living of it), most applications will require some level of validation and business rules and some level of UI logic.
The designer is really useless when it comes to developing complex logic.
You can use the designer for such situations where you don't require complex logic, however I must warn you the following cons:
The Visual Studio WPF designer produces fixed-size, fixed-position UIs. these type of UIs don't work well when executed in computers with different screen resolutions and DPI settings. Just like winforms.
It also produces XAML that has many unnecessary things (such as x:Name="categoryIdColumn" and things like Margin="13,13,43,191" which are really bad from a maintainabilty / scalability point of view)
From what I've seen, the designer-generated XAML also contains a CollectionViewSource, this is both a good thing and a bad thing. It's a good thing because it enables Design-Time Data in the DataGrid, but it is also bad because it bloats your XAML with lots of unneeded things and introduces unnecessary <Window.Resources> that complicate things up.
Now, this is the very minimal XAML needed for that DataGrid, without Design-time data support:
<Window x:Class="MiscSamples.DesignTimeDataGrid"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DesignTimeDataGrid">
<DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False">
<DataGridTextColumn Header="Category Id" Binding="{Binding CategoryId}"/>
<DataGridTextColumn Header="Name" Binding="{Binding Name}"/>
</DataGrid>
</Window>
You see? It's actually faster to type that (much more so with the help of Intellisense) than what it takes for you to browse the property window and set these properties manually.
My suggestion is that you get familiar with XAML instead of insisting in the hard way to do things
Another very important aspect to keep in mind is that generally speaking, you don't put anything in code-behind in WPF because it's not needed, therefore that tutorial is actually going against the WPF Way of doing things, but that's Ok because it's actually an Entity Framework tutorial, not a WPF tutorial.
ease of development
You really need to reconsider what you call "ease of development". When it comes to UI development, I call "ease of development" to actually being able to do what I want with the UI without having to resort to shitty procedural code practices involving P/Invoke (whatever that means) and "owner draw" type of things for evertyhing.
WPF provides REAL ease of development as opposed to the fake ease of development exhibited by winforms
winforms lets you do everything with a designer (and this is just because the code the designer generates is actually so shitty that nobody would have ever used winforms if they didn't have the designer) but then when it comes to adding complex DataBinding or UI logic you're stuck with winforms' incapabilities forever.
WPF encourages manual XAML writing, not only because XAML is declarative (as opposed to the procedural winforms approach), but also because the levels of customizability and reusability are so high that a designer-centric approach does not make sense.
drag and drop is the easy way out
No it's not. It's actually the hard way. The easy way is to learn XAML and be able to do Things you can't even imagine to do with winforms.
If a designer-centric approach still makes sense to you, you may want to try Expression Blend
Automatically Create Data Grids from Your Models
Using a data source to drag and drop a template onto a WPF control is an excellent and fast way to get up and running!
Start by doing this: In your project create a folder named Models, then use either Entity Framework DB first or code by hand the models you want to show.
OR see discussion below on Object binding...
In that same folder create a dummy class that is a property for IEnumerable like this..
public IEnumerable<MyClassModel> MyCollection { get; set; }
From there go to the Main Visual Studio menu, to View/Other Windows/Data Source and click that link.
Click on Object and find the MyCollection property just created above.
Now open a user control or window in WPF but keep the datasources toolbox opened.
It should default to a DataGrid, but you can right click on the datasource and change it to detail, datagrid or select individual properties of the class it represents.
Simply drag that datasource onto the XAML's grid area. The right click on the new stuff you see and click reset to set the content to be the size of the entire window.
After having done this you will have code injected into the code behind of the view as follows in the window loaded event of that window, usercontrol etc.
// Do not load your data at design time.
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
//Load your data here and assign the result to the CollectionViewSource.
System.Windows.Data.CollectionViewSource myCollectionViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["Resource Key for CollectionViewSource"];
myCollectionViewSource.Source = your data
// }
Go back to the XAML and look for the CollectionViewSource KEY property that was also inserted when you dragged the property to the XAML. It looks like this:
Use the Key name in the code behind, and then "Bind" the CVS to your data source which is an enumerable of type MyClassModel it can live in the View Model or in the code behind of the view as you choose.
If you only use the CollectionViewSource to as the datacontext of the grid you do not need to implement INPC for any underlying collections! The CVS updates the view automatically everytime the source is updated! Once you get good at this you can create working View prototypes of data in 2 minutes! Forget hand-coding XAML that just takes too long.
Object Binding
Create a static class with a static method that returns something like this:
When using the datasource wizard choose the "Object" selection.
Click Ok and you should see something like this:
You have just mapped all of the properties into the data source definition.
For anyone finding this issue in VS 2022: as per this is written, VS 2022 has this known bug unable to drag and drop data source to XAML form.
More info: https://developercommunity.visualstudio.com/t/drag-a-a-table-from-datasource-and-drop-in-a-windo/1660788
UPDATE:
It says that the fix has been released on 15th June. You can try updating your VS 2022 to the latest.
WPF newbie so please be gentle.
Looking to rewrite an existing VFP app in C#/WPF
All forms have containers which in turn contain textboxes, labels, etc, etc.
Using this configuration allows the user to move the container and contained controls with the mouse, set up focal points within the container to enable zooming in and out of the form, etc.
So instead of adding controls directly to the WPF form, a movable container needs to be added first and the controls added to the container.
So where to begin?
You can try the AvalonDock library to see if it can satisfy your requirement.
It sounds like one of the main things you're looking for is to add drag-and-drop ability for standard WPF panels/containers. As Mash said, AvalonDock could be of use to you, especially if you're interested in docking the panels in certain positions. But I would also suggest you taking a look at options to just add dragability to standard WPF panels. This would be a lighter-weight option to get you started quickly, without having to worry about AvalonDock's constraints.
There are certainly many ways that you could implement drag-and-drop, but a very handy capability that I think is a good fit for this task is the concept of Attached "Behaviors". Attached Behaviors basically allow you to "add on" capabilities to existing WPF controls without needing to alter or extend the actual control. There are two basic types of attached behaviors. One uses WPF Attached Properties, and the other uses what is commonly referred to as "Blend" behaviors. If you just want to get started using a bahavior to solve your immediate problem, you don't necessarily need to understand all the nuances of these two approaches, but eventually you will probably find that both of these approaches have their place, so I'd suggest reading this post about them.
In particular, there is a Blend behavior called MouseDragElementBehavior that allows you to add drag-and-drop capability to WPF panels (the "e" and "d" here are xmlns namespace prefixes):
<Border Background="LightBlue" >
<e:Interaction.Behaviors>
<b:DragBehavior/>
</e:Interaction.Behaviors>
<TextBlock Text="Drag me around!" />
</Border>
In a similar vein, you mentioned zoomability, and there is another Blend behavior that may be of use for you for that as well.
Blend behaviors are very easy to add an element if you're using Expression Blend, but you can also use them with Visual Studio. To explain how to do this, see part of Laurent's post about his magnify behavior.
I have problems figuring out where to use what xaml keywords because its hard to figure out what hierarchy it wants. It seems there is some grand design on how and where to use attributes, properties or child nodes.
<Node Attribute="True">
<Node.Property />
</Node>
I found this beautiful page explaining all the ribbon menu properties, but have no idea how to use them in xaml. After half an hour of searching and trying everything I managed to get an Icon to show in the ribbon menu button.
What is the logic behind this all and how to figure out what to use where?
How to merge the ribbon menu with the application bar (the top bar on most windows applications)? So I get a nice Ribbon Application Menu, like in the example.
Is there a way to turn off xaml background compliation? I'd sacrifice Intellisense for this.
Because the xaml editor performance is abysmal, the are many suggestions for this, but none working so far.
Edit:
I know the xaml syntax, but there's no hint on what hierarchy to use. So if I find the object I want to use (because they are all available) it will only say I'm using the wrong object, it should ask for the kind of object it wants to be in.
Also in normal programming when you use a reference you can always use all classes in it. With xaml we must suddenly know what reference our class came from, also it won't find the reference for you, you either have to try all references to see if they have a certain class or find a code example.
Good questions. Its a little hard to get a feel for exactly what you're asking for in your #1 question, but I'll take a brief stab at that one. I do have an answer for your #2 question. I do not have an answer for your #3.
"1. What is the logic behind this all and how to figure out what to use where?"
Like Clemens mentioned, the XAML Overview does a pretty good job at explaining things.
I'm guessing that one of the main things that you're asking about is basically "when do you use attribute syntax vs property element syntax". From that doc:
For some properties of an object element, attribute syntax is not possible, because the object or information necessary to provide the property value cannot be adequately expressed within the quotation mark and string restrictions of attribute syntax. For these cases, a different syntax known as property element syntax can be used....
Now about this part of your question...
"Also in normal programming when you use a reference you can always use all classes in it. With xaml we must suddenly know what reference our class came from, also it won't find the reference for you, you either have to try all references to see if they have a certain class or find a code example."
If part of your question is more about how can you more-easily handle your XAML (or more appropriately xmlns) namespaces so that it is easier to get references ironed out in your XAML, there is a technique that you may find useful. It lets you consolidate namespaces so that you can use fewer XAML namespace prefixes (or even no namespace prefixes if you take this technique to its extreme).
"2. How to merge the ribbon menu with the application bar (the top bar on most windows applications)? So I get a nice Ribbon Application Menu, like in the example."
Essentially it seems that you're asking how to: (a) extend the window chrome area (the Aero glass area) down into the client part of the window (the part that your application normally gets to put things) and (b) extend the client part of the window up into the window chrome area. If you can do both of these things, then you can end up with something that looks like Microsoft office products or modern web browsers. Fortunately there is the WPF Shell Integration Library which helps you do both of these things. I found this blog and this blog (and the source code they offer) good guides for getting started with using the WPF Shell Integration Library.
Using this library, I was able to make this window (all but the Aero color changing abilities which is a whole other topic). Notice that both of qualities I mentioned are working here (the TabControl is being display up in the normal window chrome top bar area and the window chrome Aero glass is being displayed down in the normal client area):
Here's my take
1) What is the logic behind this all and how to figure out what to use
where?
Whatever you can fit between "" can go inline like:
<TextBlock Text="{Binding Name}" />
Whatever can't, go the element way:
<TextBlock>
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} ({1})">
<Binding Path="Name" />
<Binding Path="Gender" />
</MultiBinding>
</TextBlock.Text>
</TextBlock>
2) How to merge the ribbon menu with the application bar (the top bar on
most windows applications)? So I get a nice Ribbon Application Menu,
like in the example.
You'll find more or less complicated mumbo jumbo around google, this is the essence of it:
<Window ...
WindowStyle="None" AllowsTransparency="True" Background="Transparent"
...>
<!-- Fill it up with a PNG image if you want to play with transparency -->
</Window>
Then make the ribbon the top element, and re-create Close/Maximize buttons
3) Is there a way to turn off xaml background compliation? I'd sacrifice
Intellisense for this.
Yep, it's called Notepad++
In a ListBox derived CustomControl I need to draw lines joining ListBoxItems that are layed out in a Canvas ItemsPanel.
I can achieve this by having class ListBoxLines : UIElement that does drawing in OnRender and then including that object in my ListBox ControlTemplate (but to do that I need to pipe the listbox contents to that class...)
<ControlTemplate TargetType="{x:Type p:NetworkVisualization}">
<Grid>
<p:ListBoxLines/>
<ItemsPresenter/>
</Grid>
</ControlTemplate>
Im just wondering if there is an easer way. Id really just like to add my draw code directly to my ListBox derived class but if I do that it seems to draw UNDER the listbox canvas white background.
Is there any way to to custom listbox drawing directly in my derived listbox class?
EDIT: The motivation for this question is a custom control to display nodes and linkstrengths of a wireless mesh network as in the image below:
EDIT: Additional issue: The OnRender code for ListBoxLines (the node links) is cached - how to force a redraw of this when a node is dragging? Ideally i want to build the cache with the all lines except for the currently dragging nodes lines and only redraw while dragging the lines to that node - not sure how to go about that.
Thanks for updating the question - from the original description we were on completely different pages.
Personally I would not implement a control like this, as I know from prior experience that it is not easy task. In the last two three occasions where I have needed charting I have used middle-ware solutions.
The argument for middleware is an easy case to make:
It will save you significant development time.
You will get results quicker, allowing you focus on your specific requirements.
Even if you choose a commercial provider, the time saved equates to money.
I recently evaluated charting middleware options for a project less than 5 months ago so I can tell your directly that for a WPF application the best libraries are:
Mindscape Diagrams 2 (Commercial)
Chart# (Codeplex Project, Microsoft Public License)
I have used both products for studio applications (internal, however released as if the users were clients).
...
Take a look at the above solutions, come back with further questions (if any) and then if you still want to write your own I will at the very least point you in the direction and resources to do.
A side note, you say that you like the selection part of the ListBox - did you know that the selection functionality is actually supplied by the Selector base class?