I am using UI Automation for GUI testing.
My window title contains the application name appended by a filename.
So, I want to specify Contains in my Name PropertyCondition.
I checked the overload but it is related to Ignoring the Case of the Name value.
Can anyone let me know how to specify Contains in my Name PropertyCondition?
Regards,
kvk938
I've tried solution of Max Young but could not wait for its completion. Probably my visual tree was too large, not sure. I've decided that it's my app and I should use knowledge of concrete element type I am searching for, in my case it was WPF TextBlock so I've made this:
public AutomationElement FindElementBySubstring(AutomationElement element, ControlType controlType, string searchTerm)
{
AutomationElementCollection textDescendants = element.FindAll(
TreeScope.Descendants,
new PropertyCondition(AutomationElement.ControlTypeProperty, controlType));
foreach (AutomationElement el in textDescendants)
{
if (el.Current.Name.Contains(searchTerm))
return el;
}
return null;
}
sample usage:
AutomationElement textElement = FindElementBySubstring(parentElement, ControlType.Text, "whatever");
and it worked fast.
As far as I know their is no way to do a contains while using the name property but you could do something like this.
/// <summary>
/// Returns the first automation element that is a child of the element you passed in and contains the string you passed in.
/// </summary>
public AutomationElement GetElementByName(AutomationElement aeElement, string sSearchTerm)
{
AutomationElement aeFirstChild = TreeWalker.RawViewWalker.GetFirstChild(aeElement);
AutomationElement aeSibling = null;
while ((aeSibling = TreeWalker.RawViewWalker.GetNextSibling(aeFirstChild)) != null)
{
if (aeSibling.Current.Name.Contains(sSearchTerm))
{
return aeSibling;
}
}
return aeSibling;
}
Then you would do this to get the desktop and pass the desktop with your string into the above method
/// <summary>
/// Finds the automation element for the desktop.
/// </summary>
/// <returns>Returns the automation element for the desktop.</returns>
public AutomationElement GetDesktop()
{
AutomationElement aeDesktop = AutomationElement.RootElement;
return aeDesktop;
}
Complete usage would look something like
AutomationElement oAutomationElement = GetElementByName(GetDesktop(), "Part of my apps name");
Related
I have a Microsoft Word template with some content controls. It contains a table of contents and some extra information.
On the page, I have set some content controls where I would like to inject a new text from a RESTful service. If the RESTful service returns an array of data (objects), I need to replicate the information on each page based on the Word template.
Any idea on how can I do that using the Open XML SDK (DocumentFormat.OpenXml)?
Edit:
I found this post here, which is great, but I don't know how can I apply the array of data to multiple pages from the same template.
So, how can I create multiple pages from the same template in a new document? The data comes in as an array.
The sample code below (which is unit-tested and works) does what you are trying to achieve. It is based on the following interpretation of the question and assumptions:
"Control place holders" means "Rich Text content controls", which are called block-level structured document tags (SDTs) in Open XML lingo and are thus represented by the SdtBlock class in the Open XML SDK.
The content controls have tags, meaning the relevant w:sdt elements have grandchild elements like <w:tag="tagValue" />. Those tags are used to link the data received from the REST service to the content controls.
The data is provided as a Dictionary<string, string>, mapping tag values to the content control text (data).
The general approach is to perform a pure functional transformation of the main document part of your WordprocessingDocument. The void WriteContentControls(WordprocessingDocument) method wraps the outermost pure functional transformation object TransformDocument(OpenXmlElement). The latter uses an inner pure functional transformation object TransformSdtBlock(OpenXmlElement, string).
public class ContentControlWriter
{
private readonly IDictionary<string, string> _contentMap;
/// <summary>
/// Initializes a new ContentControlWriter instance.
/// </summary>
/// <param name="contentMap">The mapping of content control tags to content control texts.
/// </param>
public ContentControlWriter(IDictionary<string, string> contentMap)
{
_contentMap = contentMap;
}
/// <summary>
/// Transforms the given WordprocessingDocument by setting the content
/// of relevant block-level content controls.
/// </summary>
/// <param name="wordDocument">The WordprocessingDocument to be transformed.</param>
public void WriteContentControls(WordprocessingDocument wordDocument)
{
MainDocumentPart part = wordDocument.MainDocumentPart;
part.Document = (Document) TransformDocument(part.Document);
}
private object TransformDocument(OpenXmlElement element)
{
if (element is SdtBlock sdt)
{
string tagValue = GetTagValue(sdt);
if (_contentMap.TryGetValue(tagValue, out string text))
{
return TransformSdtBlock(sdt, text);
}
}
return Transform(element, TransformDocument);
}
private static object TransformSdtBlock(OpenXmlElement element, string text)
{
return element is SdtContentBlock
? new SdtContentBlock(new Paragraph(new Run(new Text(text))))
: Transform(element, e => TransformSdtBlock(e, text));
}
private static string GetTagValue(SdtElement sdt) => sdt
.Descendants<Tag>()
.Select(tag => tag.Val.Value)
.FirstOrDefault();
private static T Transform<T>(T element, Func<OpenXmlElement, object> transformation)
where T : OpenXmlElement
{
var transformedElement = (T) element.CloneNode(false);
transformedElement.Append(element.Elements().Select(e => (OpenXmlElement) transformation(e)));
return transformedElement;
}
}
This should provide enough input for implementing your specific solution even if the details vary (e.g., regarding how you map your array of data to the specific content controls). Further, if you don't use block-level structured document tags (SdtBlock, Rich Text content controls) but but rather inline-level structured document tags (SdtRun, plain text content controls), the principle is the same. Instead of the Paragraph instances (w:p elements) contained in SdtContentBlock instances, you would have Run instances (w:r elements) contained in SdtContentRun instances.
Update 2019-11-23: My CodeSnippets GitHub repository contains the code for the ContentControlWriter and AltChunkAssemblyTests classes. The latter shows how the ContentControlWriter class can be used.
I had a similar problem as the user posting at the following location:
Cross-Process Drag and Drop of custom object type in WinForms C#
Luckily, I have figured out how to serialize almost all parts of my custom object except for a SortedList object.
I need this object because it contains some pretty crucial information to my application, and the Xml nesting is pretty messy.
When I comment out the line adding the SortedList in the ISerializable member GetObjectData(), the object makes it across to the new app. When I leave it in, it doesn't, and I can't figure out how to get it serialized.
I have done some looking both here on StackOverflow and on the web, but have found nothing of use.
I am using the following code to check if my object is serializable so it can be drag & dropped to another application:
/// <summary>
/// Determine if object can be fully serializable to binary format.
/// </summary>
/// <param name="obj"></param>
/// <param name="errorMsg">If return value false, contains reason for failure.</param>
/// <returns></returns>
public static bool IsSerializable(object obj, out string errorMsg)
{
errorMsg = "";
using (MemoryStream mem = new MemoryStream())
{
BinaryFormatter bin = new BinaryFormatter();
try
{
bin.Serialize(mem, obj);
return true;
}
catch (Exception ex)
{
errorMsg = string.Format("Object cannot be serialized: {0}", ex.ToString());
return false;
}
}
}
Does anyone have any suggestions that can help me out? I would like to keep my list of XmlNodes intact during the drag/drop if possible, but wouldn't be opposed to doing some additional coding to break it up into serialize-able pieces and reconstructing it on the other side. The important thing is that the end result must contain a SortedList.
If necessary, I can provide the contents of my custom object I am serializing for drag and drop if it will help.
Thanks,
Kyle K.
I finally figured out how to correctly serialize my object. I was using a SortedList of XmlNodes, which I found out the XmlNode object is not serializable. I switched my implementation to contain a SortedList of strings, and now everything works just fine.
Thanks,
Kyle
Hi all I'm trying to get to grips with using MVVM, but I'm having a hard time :(, firstly for my question, I'm using the code provide in this MVVM article as a template for my learning.
My question is simple how do expose independent commands, in this case he has create a list of hyperlinks, but how do i create a single button that's fixed and does the same as the 'create new customer' link.
I created something like this(was added to the MainWindowViewModel.cs):
public CommandViewModel exposedCommand
{
get
{
return new CommandViewModel(
Strings.MainWindowViewModel_Command_CreateNewCustomer,
new RelayCommand(param => this.CreateNewCustomer())
);
}
}
and then in the xaml document i created a new button, this was added to the MainWindow.xaml
<Button
Content="Button"
Height="23"
HorizontalAlignment="Left"
Margin="6,303,0,0" Name="button1" VerticalAlignment="Top" Width="150"
Command="{Binding Path=exposedCommand}"
/>
I am not to sure if I'm missing something, or what I am where going wrong,
Soz if I sounding a bit naive I have only just started using MVVM and routed commands and so.
Oh another thing it does load the link it just doesn't create the tab, in other words if you would to add
Console.Writeline("HERE");
to the exposedCommand method
It would print out 'HERE' it just won't do anything when you click the button.
Thanks Any Help would be so appreciated.
Your XAML code is correct.
I also started off with Josh Smith's MVVM article.
Below is a stripped down example of how I implement Commands in my ViewModels:
public class ProjectViewModel : ViewModelBase
{
// Private variable for holding save command
private RelayCommand _saveCommand;
// Other fields here
// Constructors and properties and stuff here
// Command Property for Save button. Bind XAML to "SaveCommand"
public ICommand SaveCommand
{
get
{
if (_saveCommand == null) // Init command on first get
_saveCommand = new RelayCommand(param => this.SaveChanges(), param => this.CanSave);
return _saveCommand;
}
}
/// <summary>
/// Method called when save command is executed
/// </summary>
private void SaveChanges()
{
// Save logic here...
}
/// <summary>
/// Predicate for determining if SaveCommand is enabled
/// </summary>
private bool CanSave
{
get
{
return true; // Replace with SaveCommand predicate logic
}
}
}
If it still does not work, check you runtime output for BindingErrors. If there is a BindingError that implies that the View cannot find the SaveCommand, then your ViewModel is not correctly set to be the DataContext of the View. Let me know in the comments if this is the problem.
You can bind command to only those objects that has an implementation of ICommand interface.
In your example you are binding with view model object.
Instead of this create a property in view model that is a type of RelayCommand and bind this with button.
It should work.
The first thing that concerns me is your the code inside the getter of you property. You're returning a new object EVERY TIME the exposedCommand is accessed. That's not really recommended, you should store that in a backing property like so:
CommandViewModel _exposedCommand;
public CommandViewModel exposedCommand
{
get
{
if (_exposedCommand == null)
{
_exposedCommand = new CommandViewModel(
Strings.MainWindowViewModel_Command_CreateNewCustomer,
new RelayCommand(param => this.CreateNewCustomer()));
}
return _exposedCommand;
}
}
That being said the typical way to present your desired ICommand property is something like this:
RelayCommand _exposedCommand;
public ICommand exposedCommand
{
get
{
if (_exposedCommand == null)
_exposedCommand= new RelayCommand(param => this.CreateNewCustomer());
return _exposedCommand;
}
}
I have a code template with a variable and I would like to capitalize(just the first letter) the value of this variable only in some occurrences. Is there a way to do this?
The template code is as follows - I would like to capitalize Property Name in my function names...
private $$${PropertyName};
${cursor}
public function get${PropertyName}()
{
return $$this->${PropertyName};
}
public function set${PropertyName}($$value)
{
$$this->${PropertyName} = $$value;
}
Please Note: This is a template for use with code templates in the IDE (not in PHP). For details see: http://www.ibm.com/developerworks/opensource/tutorials/os-eclipse-code-templates/index.html
I also want this and tried to build a custom TemplateVariableResolver to do it. (I already have one custom resolver in place that generates new UUIDs a la http://dev.eclipse.org/blogs/jdtui/2007/12/04/text-templates-2/.)
I made a custom resolver bound to capitalize:
public class CapitalizingVariableResolver extends TemplateVariableResolver {
#Override
public void resolve(TemplateVariable variable, TemplateContext context) {
#SuppressWarnings("unchecked")
final List<String> params = variable.getVariableType().getParams();
if (params.isEmpty())
return;
final String currentValue = context.getVariable(params.get(0));
if (currentValue == null || currentValue.length() == 0)
return;
variable.setValue(currentValue.substring(0, 1).toUpperCase() + currentValue.substring(1));
}
}
(plugin.xml:)
<extension point="org.eclipse.ui.editors.templates">
<resolver
class="com.foo.CapitalizingVariableResolver"
contextTypeId="java"
description="Resolves to the value of the variable named by the first argument, but with its first letter capitalized."
name="capitalized"
type="capitalize">
</resolver>
</extension>
that I would use like this: (I am working in Java; I see that you do not appear to be)
public PropertyAccessor<${propertyType}> ${property:field}() {
return ${property};
}
public ${propertyType} get${capitalizedProperty:capitalize(property)}() {
return ${property}.get();
}
public void set${capitalizedProperty}(${propertyType} ${property}) {
this.${property}.set(${property});
}
As of Eclipse 3.5, the problem I am having is that my custom resolver does not get a chance to re-resolve once I've specified a value for the property variable. It appears that the Java Development Tools (Eclipse JDT) do this dependent template variable re-resolution via a mechanism called MultiVariableGuess within the JavaContext (see addDependency()). Unfortunately for us, that mechanism does not seem to be exposed, so I/we can't use it to do the same (without lots of copy-and-paste or other redundant work).
At this point, I am giving up again for a while and will keep typing the leading-lowercase and leading-uppercase names separately into two independent template variables.
In MVC2 template, I normally use this.ViewData.TemplateInfo.GetFullHtmlFieldId(fieldName)
to generate the id field of an html element. This has worked in most of the cases.
However this method does not actually return valid id field, it merely prefix fieldName with ViewData.TemplateInfo.HtmlFieldPrefix, this is causing problems for me when rendering collections which has [] in the HtmlFieldPrefix.
I have been manually converting those characters to _ where I find the need, but this seems to be not elegant (repeated code), has anyone found a good way to generate id field properly?
Can you be more specific about the kind of problems do you have?
For example, there is an elegant approach to editing variable length list with validation support provided. While it doesn't use templates still remains DRY with partial views.
While the ids are inconsistent - the names are OK and only problem I encountered is that using jquery.infieldlabel it appeared that label's for attribute (generated by GetFullHtmlFieldId inside LabelFor helper) didn't match id of the appropriate TextBoxFor input. So I created LabelForCollectionItem helper method that just uses the same method for id generation as the TextBox - TagBuilder.GenerateId(fullName)
Maybe the code doesn't correspond to your need but hope it will help somebody since I found your question among the first searching for solution to my problem.
public static class LabelExtensions
{
/// <summary>
/// Generates Label with "for" attribute corresponding to the id rendered by input (e.g. TextBoxFor),
/// for the case when input is a collection item (full name contains []).
/// GetFullHtmlFieldId works incorrect inside Html.BeginCollectionItem due to brackets presense.
/// This method copies TextBox's id generation.
/// </summary>
public static MvcHtmlString LabelForCollectionItem<TModel, TValue>(this HtmlHelper<TModel> html, Expression<Func<TModel, TValue>> expression,
string labelText = null, object htmlAttributes = null) where TModel : class
{
var tag = new TagBuilder("label");
tag.MergeAttributes(new RouteValueDictionary(htmlAttributes)); // to convert an object into an IDictionary
// set inner text
string htmlFieldName = ExpressionHelper.GetExpressionText(expression);
string innerText = labelText ?? GetDefaultLabelText(html, expression, htmlFieldName);
if (string.IsNullOrEmpty(innerText))
{
return MvcHtmlString.Empty;
}
tag.SetInnerText(innerText);
// set for attribute
string forId = GenerateTextBoxId(tag, html, htmlFieldName);
tag.Attributes.Add("for", forId);
return MvcHtmlString.Create(tag.ToString(TagRenderMode.Normal));
}
/// <summary>
/// Extracted from System.Web.Mvc.Html.InputExtensions
/// </summary>
private static string GenerateTextBoxId<TModel>(TagBuilder tagBuilder, HtmlHelper<TModel> html, string htmlFieldName)
{
string fullName = html.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(htmlFieldName);
tagBuilder.GenerateId(fullName);
string forId = tagBuilder.Attributes["id"];
tagBuilder.Attributes.Remove("id");
return forId;
}
/// <summary>
/// Extracted from System.Web.Mvc.Html.LabelExtensions
/// </summary>
private static string GetDefaultLabelText<TModel, TValue>(HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TValue>> expression, string htmlFieldName)
{
var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
string labelText = metadata.DisplayName ?? metadata.PropertyName ?? htmlFieldName.Split('.').Last();
return labelText;
}
}