WordPress database error: [INSERT, UPDATE command denied to user '51213-2'@'10.10.20.57' for table 'wp_options']INSERT INTO `wp_options` (`option_name`, `option_value`, `autoload`) VALUES ('_transient_doing_cron', '1714854491.0593810081481933593750', 'yes') ON DUPLICATE KEY UPDATE `option_name` = VALUES(`option_name`), `option_value` = VALUES(`option_value`), `autoload` = VALUES(`autoload`)
<\/a>In the previous post<\/a>, we have seen that setting the AutomationId can greatly help us when we want to perform some UI Tests.<\/p>\n Todyay, I struggled with a problem which seems common after some digging on the net : the TextBlock control is not found and no assertion can be set on it. In this post we’ll see why this happen and how to solve this issue. The problem comes from the TextBlockAutomationPeer. If you digg into its code you can find this : This basically means that if the TextBlock is inside a template, any kind of template, it is not exposed.<\/strong> The only dirty solution I find is to create your own TextBlock control with its own corrected AutomationPeer. <\/strong> The code to write is really light. The real issue is that you have to update every TextBlock usage in the XAML of your application. \/\/The corrected AutomationPeer is based on the TextBlockAutomationPeer protected override bool IsControlElementCore() Finally, the demo app XAML needs to be updated:
\nBut it does not always occur and it is then difficult to debug this strange behavior.<\/strong><\/p>\n
\n<\/p>\nWhy and When ?<\/h3>\n
\n[csharp]override protected bool IsControlElementCore()
\n{
\n return ((TextBlock)Owner).TemplatedParent == null;
\n} [\/csharp]<\/p>\n
\nFor example, if in an ItemsControl, a Listbox or another control, you use a DataTemplate containing a TextBlock, this one won’t be find by the automation client. Here is a code example :
\n[xml]<Grid>
\n <Grid.Resources>
\n <DataTemplate x:Key="ItemTemplate">
\n <TextBlock Text="{Binding }" \/>
\n <\/DataTemplate>
\n <\/Grid.Resources>
\n <ListBox ItemsSource="{Binding }"
\n ItemTemplate="{StaticResource ItemTemplate}" \/>
\n<\/Grid>[\/xml]<\/p>\nA solution<\/h3>\n
\nIt will be based on the original TextBlockAutomationPeer but the IsControlElementCore method will always return true.
\nAs a bonus, I let commented a snippet which will expose the TextBlock only if an AutomationId is set on it.<\/p>\n
\n[csharp]
\npublic class AutomatisableTextBlock : TextBlock
\n{
\n protected override AutomationPeer OnCreateAutomationPeer()
\n {
\n return new AlwaysVisibleTextBlockAutomationPeer(this);
\n }
\n}<\/p>\n
\npublic class AlwaysVisibleTextBlockAutomationPeer : TextBlockAutomationPeer
\n{
\n public AlwaysVisibleTextBlockAutomationPeer(TextBlock t)
\n : base(t) { }<\/p>\n
\n {
\n \/\/if (String.IsNullOrEmpty(GetAutomationId()))
\n \/\/ return false;
\n return true;
\n }
\n}
\n[\/csharp]<\/p>\n
\n[xml]
\n<Grid>
\n <Grid.Resources>
\n <DataTemplate x:Key="ItemTemplate">
\n <local:AutomatisableTextBlock Text="{Binding }" \/>
\n <\/DataTemplate>
\n <\/Grid.Resources>
\n <ListBox ItemsSource="{Binding }"
\n ItemTemplate="{StaticResource ItemTemplate}" \/>
\n<\/Grid>[\/xml]<\/p>\n