0

I want to bind AutomationProperties.Name to text that containd in secondTextBox how to do that? Using only xaml without code behind.

Xaml:

<Window x:Class="WpfApplication5.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApplication5"
        xmlns:converters="clr-namespace:WpfApplication5.Converters"
        mc:Ignorable="d"
        Title="TestWindow" Height="350" Width="525">
    <Window.Resources>
        <converters:StrangeConverter x:Key="CommonConverter"/>
    </Window.Resources>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <Grid.RowDefinitions>
                <RowDefinition></RowDefinition>
                <RowDefinition></RowDefinition>
            </Grid.RowDefinitions>
            <ComboBox Height="20" Width="100" ItemsSource="{Binding comboBoxItems}" AutomationProperties.AutomationId="ID_COMBO1">
                <ComboBox.ItemContainerStyle>
                    <Style>
                        <!--<Setter Property="AutomationProperties.Name" Value="{Binding UniqNumber}"/>-->
                        <Setter Property="AutomationProperties.Name" Value="{Binding Path=Text, ElementName=secondTextBox}"/>
                    </Style>
                </ComboBox.ItemContainerStyle>
                <ComboBox.ItemTemplate>
                    <DataTemplate>
                        <TextBlock x:Name="secondTextBox">
                            <Run Text="{Binding Name}"></Run>
                            <Run Text="-"></Run>
                            <Run Text="{Binding UniqNumber}"></Run>
                            <Run Text="{Binding .,Converter={StaticResource CommonConverter}}"></Run>
                        </TextBlock>
                    </DataTemplate>
                </ComboBox.ItemTemplate>
            </ComboBox>
        </Grid>
        <ComboBox Height="20" Width="100" ItemsSource="{Binding comboBoxItems}" AutomationProperties.AutomationId="ID_COMBO2"/>
        <Button Grid.Row="1"  Height="20" Width="100" Click="Button_Click"/>
    </Grid>
</Window>

Converter:

namespace WpfApplication5.Converters
{
    class StrangeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            return "Test";
        }

        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

Code:

namespace WpfApplication5
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        ViewModel Vm = new ViewModel();
        public MainWindow()
        {
            InitializeComponent();
            DataContext = Vm;
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            var _calculatorAutomationElement = AutomationElement.RootElement.FindFirst(TreeScope.Children, new PropertyCondition(AutomationElement.NameProperty, "TestWindow"));
            var combobox = _calculatorAutomationElement.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.AutomationIdProperty, "ID_COMBO1"));
            Vm.SelectComboboxItem(combobox, "02 - Basic Get");
            combobox = _calculatorAutomationElement.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.AutomationIdProperty, "ID_COMBO2"));
            Vm.SelectComboboxItem(combobox, "01 - Basic Set");
        }
    }

    public class ViewModel
    {
        public List<Item> comboBoxItems { get; set; }

        public ViewModel()
        {
            comboBoxItems = new List<Item>();
            comboBoxItems.Add(new Item { Name = "Basic Get", UniqNumber = 1 });
            comboBoxItems.Add(new Item { Name = "Basic Set", UniqNumber = 2 });
            comboBoxItems.Add(new Item { Name = "Basic Report", UniqNumber = 3 });

        }

        public bool SelectComboboxItem(AutomationElement comboBox, string item)
        {
            (comboBox.GetCurrentPattern(ExpandCollapsePattern.Pattern) as ExpandCollapsePattern).Expand();
            PropertyCondition findCondition = new PropertyCondition(AutomationElement.NameProperty, item);
            var comboBoxItems = comboBox.FindFirst(TreeScope.Children, findCondition);
            if (comboBoxItems != null)
            {
                var selectionItemPattern = comboBoxItems.GetCurrentPattern(SelectionItemPattern.Pattern) as SelectionItemPattern;
                selectionItemPattern.Select();
                return true;
            }
            return false;
        }
    }

    public class Item
    {
        public string Name { get; set; }

        public int UniqNumber { get; set; }
    }
}
A191919
  • 3,422
  • 7
  • 49
  • 93
  • You should create a property like `TextToDisplay` in your `Item` class and calculate the it there instead of the xaml. And then you can bind the `AutomationProperties.Name` to this property – Piyush Parashar Aug 10 '17 at 10:59
  • It's a pity but i need to do this in xaml. – A191919 Aug 10 '17 at 11:04
  • Check my answer. It is still bound in XAML – Piyush Parashar Aug 10 '17 at 11:07
  • @PiyushParashar, you answer does not contain Converter. I am trying to solve this problem without a lot of code behind. – A191919 Aug 10 '17 at 11:10
  • Lot of code behind?? I hardly added any code behind. Just one property. The converter logic remains as is. It just moves to this property now in the getter. This would be the recommended way to doing it. But if you are really bent on doing it in XAML, have you tried using RelativeSource=Self and binding the `Autoproperties.Name` to `Text` property? – Piyush Parashar Aug 10 '17 at 11:16
  • 1
    @PiyushParashar Note that RelativeSource=Self won't work. The properties are set on two different objects, i.e. the TextBlock in the DataTemplate and the ComboBoxItem in the ItemContainerStyle. – Clemens Aug 10 '17 at 11:21
  • @Clemens, this is the main problem.... – A191919 Aug 10 '17 at 11:22
  • If you want to avoid an additional view model property, you could bind both properties with a MultiBinding and an appropriate multi-value converter. Or just an appropriate StringFormat. – Clemens Aug 10 '17 at 11:23
  • @Clemens @A191919 - My bad!! I missed the style section in `ItemContainerStyle`. I thought you meant to add the `AutomationProperties.Name` to the TextBlock it self. – Piyush Parashar Aug 10 '17 at 11:28

2 Answers2

0

Update the Item class as:

public class Item
{
    private string _TextToDisplay;
    public string Name { get; set; }

    public int UniqNumber { get; set; }

    public string TextToDisplay
    {
        get
        {
            _TextToDisplay  = Name + "-" + UniqNumber;  //Add other modification from converter
            return _TextToDisplay;               
        }
        set
        {
            _TextToDisplay = value;
        }
    }
}

Bind the AutomationProperties.Name to this property

<TextBlock x:Name="secondTextBox" Text="{Binding TextToDisplay}" AutomationProperties.Name="{Binding TextToDisplay}">
Clemens
  • 123,504
  • 12
  • 155
  • 268
Piyush Parashar
  • 866
  • 8
  • 20
0

This should work without additional view model property and without converter:

<ComboBox.ItemContainerStyle>
    <Style TargetType="ComboBoxItem">
        <Setter Property="AutomationProperties.Name">
            <Setter.Value>
                <MultiBinding StringFormat="{}{0} - {1} Test">
                    <Binding Path="Name"/>
                    <Binding Path="UniqNumber"/>
                </MultiBinding>
            </Setter.Value>
        </Setter>
    </Style>
</ComboBox.ItemContainerStyle>
<ComboBox.ItemTemplate>
    <DataTemplate>
        <TextBlock>
            <TextBlock.Text>
                <MultiBinding StringFormat="{}{0} - {1} Test">
                    <Binding Path="Name"/>
                    <Binding Path="UniqNumber"/>
                </MultiBinding>
            </TextBlock.Text>
        </TextBlock>
    </DataTemplate>
</ComboBox.ItemTemplate>
Clemens
  • 123,504
  • 12
  • 155
  • 268
  • But how to use converter in MultiBinding in tag Binding? In this case i should implement new IMultiConverter. – A191919 Aug 10 '17 at 11:30
  • Set the MultiBinding's Converter property to an instance of a class that implements IMultiValueConverter. Although it doesn't seem to be necessary here... – Clemens Aug 10 '17 at 11:32