I’m grabbing the text from each cell of the first row of an HTML table, and storing them in a Dictionary (of string, object). So a Get Text with output of ItemDict(“Item ID”) gets the Item ID from the first column of the table. Another Get Text with output of ItemDict(“Customer”) gets the customer name from the second column of the table. Etc.
One of the columns has a link in it (tag = A). I want to get this as a UiElement. I used Find Element and set its output to ItemDict(“Claim Link UiElement”) and it works fine. On looping through the ItemDict keys it even reports that ItemDict(“Claim Link UiElement”).ToString is a UiElement.
But when I try to use ItemDict(“Claim Link UiElement”) as the target of a Click activity, I get an error about not supporting conversion from Object to UiElement. So far I got around this by setting up a UiElement variable outside the Dictionary, and storing the UiElement in there. This isn’t ideal, though, as there should be a way to store the UiElement in the Dictionary as an object and get it back out as a UiElement, I just haven’t found out how.
If it matters, the point to using a Dictionary here is to store everything in a single variable that I can pass as a single item to other things, as this is a custom activity I’m writing that will be used within other automations. Those automations should be able to get the Dictionary as an output from the custom activity and then reference the keys in the Dictionary, including being able to click the link UiElement.
Figures. 2 minutes after posting that I found the solution.
Find Item puts UiElement into local variable LinkUiElement.
Then Assign ItemDict(“Link UiElement”) to value LinkUiElement. Now the UiElement is stored in the Dictionary.
To use it in a Click (or any other activity that requires UiElement), instead of just putting ItemDict(“Link UiElement”) into the Element property of the activity, you have to put DirectCast(ItemDict(“Link UiElement”),UiElement) into the Element property.
Of course, this is actually a less desirable solution than using a separate output argument to store the UiElement outside the Dictionary. That way whoever uses my custom activity in their project can just directly reference the name of the output argument, they don’t have to bother doing the DirectCast in all their activities.
I tried your suggestion Paul – I’m afraid this is not a good solution. Great idea, but wrought with problems that seem to stem from the huge amount of data that often is stored in UiElements. I followed your advice, only I used CType to cast my dictionary-stored (even tried datatable-stored) UiElements back to a variable before using in my Click activities, and I didn’t always get the 2nd element back out; never get more than that out of WITH it being valid. I found a lot of data gets lost storing the entire UiElement in a dictionary (and even a small datatable).
Did you find success gathering more than just a few UiElements in your Dictionary, and ensuring none of them had "!"s or "null"s for the UiElement’s Attributes, Selector, _cachedAttributes or _cachedSelector properties?
My solution – since I use the UiElements almost immediately later, in the next step of my automation – was to save the UiElement.Selector as a String in my dictionary, and using that as the Strict Selector for my later Click activites. (The object repository would’ve been my 1st choice if I needed to continually revisit the exact same UiElements; mine being different appointments that span different months means my UiElements are always changing day by day)
You mentioned storage in your title, “and then get it back out” – as if to use later, arguably even as an argument to another workflow.
And I’m afraid your idea doesn’t always work. As I did exactly what you just suggested: stored in a dictionary – the entire UiElement – and pulled them out as needed via the Key. Just to find null and COM Exception errors. I posted to help others as your solution fails, two years later.