You have obviously chosen the wrong tool to accomplish your task.
Automation is designed to work with UI elements, but you need data for the task.
See what the Visual Tree of your DataGrid looks like:
DataGrid is inherited from ItemsControl. And in his visualization there are only rows. No columns.
It is possible to extract data from a specific cell, but it is very difficult and does not make sense.
You need to create a normal Data source.
To get started, take some kind of implementation of INotifyPropertyChanged.
For example, this:
/// <summary>Base class implementing INotifyPropertyChanged.</summary>
public abstract class BaseINPC : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>Called AFTER the property value changes.</summary>
/// <param name="propertyName">The name of the property.
/// In the property setter, the parameter is not specified. </param>
public void RaisePropertyChanged([CallerMemberName] string propertyName = "")
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
/// <summary> A virtual method that defines changes in the value field of a property value. </summary>
/// <typeparam name = "T"> Type of property value. </typeparam>
/// <param name = "oldValue"> Reference to the field with the old value. </param>
/// <param name = "newValue"> New value. </param>
/// <param name = "propertyName"> The name of the property. If <see cref = "string.IsNullOrWhiteSpace (string)" />,
/// then ArgumentNullException. </param>
/// <remarks> If the base method is not called in the derived class,
/// then the value will not change.</remarks>
protected virtual void Set<T>(ref T oldValue, T newValue, [CallerMemberName] string propertyName = "")
{
if (string.IsNullOrWhiteSpace(propertyName))
throw new ArgumentNullException(nameof(propertyName));
if ((oldValue == null && newValue != null) || (oldValue != null && !oldValue.Equals(newValue)))
OnValueChange(ref oldValue, newValue, propertyName);
}
/// <summary> A virtual method that changes the value of a property. </summary>
/// <typeparam name = "T"> Type of property value. </typeparam>
/// <param name = "oldValue"> Reference to the property value field. </param>
/// <param name = "newValue"> New value. </param>
/// <param name = "propertyName"> The name of the property. </param>
/// <remarks> If the base method is not called in the derived class,
/// then the value will not change.</remarks>
protected virtual void OnValueChange<T>(ref T oldValue, T newValue, string propertyName)
{
oldValue = newValue;
RaisePropertyChanged(propertyName);
}
}
On its basis you can create a type for collection edements:
public class PersonVM : BaseINPC
{
private string _name;
private uint _age;
private string _mail;
public string Name { get => _name; set => Set(ref _name, value); }
public uint Age { get => _age; set => Set(ref _age, value); }
public string Mail { get => _mail; set => Set(ref _mail, value); }
}
And ViewModel with collection:
public class ViewModel
{
public ObservableCollection<PersonVM> People { get; }
= new ObservableCollection<PersonVM>()
{
new PersonVM(){Name="Peter", Age=20, Mail="[email protected]"},
new PersonVM(){Name="Alex", Age=30, Mail="[email protected]"},
new PersonVM(){Name="Nina", Age=25, Mail="[email protected]"},
};
}
Connect it to the DataContext Windows:
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid>
<ListView Margin="10" ItemsSource="{Binding People}">
<ListView.View>
<GridView x:Name="ListViewItem" >
<GridViewColumn x:Name="Name1" Header="Name" Width="120" DisplayMemberBinding="{Binding Name}" />
<GridViewColumn Header="Age" Width="50" DisplayMemberBinding="{Binding Age}" />
<GridViewColumn Header="Mail" Width="150" DisplayMemberBinding="{Binding Mail}" />
</GridView>
</ListView.View>
</ListView>
</Grid>
Now your task is reduced to finding the desired item in the People collection.