Set a Unique Automation Property for Silverlight Controls for Testing

If you want to run coded UI tests or create action recordings for your Silverlight 4 application, you must have a unique automation property that identifies each control. For more information about how to set up your Silverlight application so that the controls are recognized, see How to: Set Up Your Silverlight Application for Testing.

You can assign a unique automation property based on the type of Silverlight control in your application. This topic covers how to assign this unique automation property in the following situations:

  • Static XAML definition of controls

  • Assign unique automation properties using Expression Blend

  • Use a DataTemplate

  • Use a control template

  • Data Grids

  • Dynamic controls

Methods to Use to Assign a Unique Automation Property

Static XAML Definition

To specify a unique automation property for a control that is defined in your XAML file, you can set the AutomationProperties.AutomationId or AutomationProperties.Name implicitly or explicitly, as shown in the following examples. Setting either of these values gives the control a unique automation property that can be used to identify the control when you create a coded UI test or action recording.

Set the Property Implicitly

Set the AutomationProperties.AutomationId to ButtonX using the Name property in the XAML for the control.

<Button Name="ButtonX" Height="31" HorizontalAlignment="Left" Margin="23,26,0,0"  VerticalAlignment="Top" Width="140" Click="ButtonX_Click" />

Set the AutomationProperties.Name to ButtonY using the Content property in the XAML for the control.

<Button Content="ButtonY" Height="31" HorizontalAlignment="Left" Margin="23,76,0,0" VerticalAlignment="Top" Width="140" Click="ButtonY_Click" />

Set the Property Explicitly

Set the AutomationProperties.AutomationId to ButtonX explicitly in the XAML for the control.

<Button AutomationProperties.AutomationId=“ButtonX” Height="31" HorizontalAlignment="Left" Margin="23,26,0,0"  VerticalAlignment="Top" Width="140" Click="ButtonX_Click" />

Set the AutomationProperties.Name to ButtonY explicitly in the XAML for the control.

<Button AutomationProperties.Name="ButtonY" Height="31" HorizontalAlignment="Left" Margin="23,76,0,0" VerticalAlignment="Top" Width="140" Click="ButtonY_Click" />

Assign Unique Automation Properties Using Expression Blend

You can also use Expression Blend 3 or later to assign unique names to interactive elements such as buttons, list boxes, combo boxes and text boxes. This gives the control a unique value for AutomationProperties.Name. Use one of the following methods to do this from Expression Blend.

Note

You can only use this method for controls that are created statically using XAML.

To Give a Unique Name to Existing Controls

On the Tools menu, click Name Interactive Elements, as shown in the following illustration.

Use Expression Blend to assign unique names

To Automatically Give a Unique Name to Controls That You Create

On the Tools menu, point to Options, and then click Project. Select Automatically name interactive elements on creation and then click OK, as shown in the following illustration.

Assign Unique Names with Expression Blend

Use a Data Template

You can define a simple template using ItemTemplate to bind the values in a list box to variables using the following XAML.

<ListBox Name="listBox1 ItemsSource="{Binding Source={StaticResource employees}}">
   <ListBox.ItemTemplate>
      <DataTemplate>
         <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding EmployeeName}" />
            <TextBlock Text="{Binding EmployeeID}" />
         </StackPanel>
      </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>

You can also use a template with ItemContainerStyle to bind the values to variables by using the following XAML.

      <ListBox Name="listBox1 ItemsSource="{Binding Source={StaticResource employees}}">
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="ListBoxItem">
                                <Grid>
                                    <Button Content="{Binding EmployeeName}" AutomationProperties.AutomationId="{Binding EmployeeID}"/>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>         
        </ListBox>

For both of these examples, you must then override the ToString() method of ItemSource, as shown using the following code. This code makes sure that the AutomationProperties.Name value is set and is unique, because you cannot set a unique automation property for each data bound list item using binding. Setting a unique value for the Automation Properties.Name is sufficient in this case.

Note

Using this approach, the inner contents of the list item can also be set to a string in the Employee class through binding. As shown in the example, the button control inside each list item is assigned a unique automation id which is the Employee ID.

Employee[] employees = new Employee[] 
{
   new Employee("john", "4384"),
   new Employee("margaret", "7556"),
   new Employee("richard", "8688"),
   new Employee("george", "1293")
};

listBox1.ItemsSource = employees;

public override string ToString()
{
    return EmployeeName + EmployeeID; // Unique Identification to be set as the AutomationProperties.Name
}

Use a Control Template

You can use a control template so that each instance of a specific type obtains a unique automation property when it is defined in the code. You must create the template so that the AutomationProperty binds to a unique ID in the control instance. The following XAML demonstrates one approach to create this binding with a control template.

<Style x:Key="MyButton" TargetType="Button">
<Setter Property="Template">
   <Setter.Value>
<ControlTemplate TargetType="Button">
   <Grid>
      <CheckBox HorizontalAlignment="Left" AutomationProperties.AutomationId="{TemplateBinding Content}"></CheckBox>
      <Button Width="90" HorizontalAlignment="Right" Content="{TemplateBinding Content}" AutomationProperties.AutomationId="{TemplateBinding Content}"></Button>
   </Grid>
</ControlTemplate>
   </Setter.Value>
</Setter>
</Style>

When you define two instances of a button using this control template, the automation id is set to the unique content string for the controls in the template, as shown in the following XAML.

<Button Content=”Button1” Style="{StaticResource MyButton}" Width="140"/>
<Button Content=”Button2” Style="{StaticResource MyButton}" Width="140"/>

Data Grids

The following XAML gives an example of a Silverlight data grid control that is bound to data.

<Grid >
<data:DataGrid Name="Details" Margin="5" HeadersVisibility="All" AutoGenerateColumns="False" >
<data:DataGrid.Columns>
<data:DataGridTextColumn Header="Name"
Binding="{Binding name}" />
<data:DataGridTextColumn Header="Age"
Binding="{Binding age}" />
<data:DataGridTextColumn Header="Education"
Binding="{Binding education}" />

</data:DataGrid.Columns>
</data:DataGrid>
</Grid>

The following code shows how the data grid content is populated from an item source.

List<PersonalDetails> persons = new List<PersonalDetails>();
String[] Education = { "High School", "Graduate", "Post Graduate" };
for (int i=0; i<10; i++)
   {
      persons.Add(new PersonalDetails()
      {
          name = "name" + i,
          education = Education[i%3],
          age = 20 + i + i/2 + i*2
      });
   }
Details.ItemsSource = persons;

By default, this code will assign the same value for AutomationProperties.Name to each row in the data grid. This value is the value returned by ToString() for the PersonalDetails object. To change this value to be unique for each row in the data grid, you must override the ToString() method of the ItemsSource method. For example, you can use the following code to override the ToString() method so that it returns a unique value that is then assigned to AutomationProperties.Name.

public override string ToString()
   {
       return name.ToString() + age.ToString();
   }

Dynamic Controls

If you have controls that are created dynamically from your code and not created statically or through templates in XAML files, you must set the Content or Name properties for the control. This makes sure that each dynamic control has a unique automation property. For example, if you have a check box that must be displayed when you select a list item, you can set these properties, as shown in the following code example.

private void CreateCheckBox(string txt, StackPanel panel)
   {
      CheckBox cb = new CheckBox();
      cb.Content = txt; // Sets the AutomationProperties.Name
      cb.Height = 50;
      cb.Width = 100;
      cb.Name = "DynamicCheckBoxAid"+ txt; // Sets the AutomationProperties.AutomationId
      panel.Children.Add(cb);
    }

See Also

Other Resources

Testing Silverlight Applications with Coded UI Tests or Action Recordings