Add a SelectedCustomer Property

This is the current state. The Text property of the TextBox is bound to the SelectedItem property of the ListView so that the FirstName of the selected customer displays in the TextBox.

However, the binding was achieved through UI logic in XAML. The ViewModel has no idea what Customer is selected.

To solve for this, created a SelectedCustomer property in the ViewModel and bind it to the SelectedItem in the ListView. The SelectedCustomer has a FirstName property; bind it to the Text in the TextBox. This effectively moves the selection logic to the ViewModel:

MainViewModel.cs

public class MainViewModel
{
    private readonly ICustomerDataProvider _customerDataProvider;

    // Using an interface prevents MainViewModel from being tightly coupled to DataProvider
    public MainViewModel(ICustomerDataProvider customerDataProvider) {  }

    // A collection type that notifies the data binding when items are added or removed
    public ObservableCollection<Customer> Customers { get; } = new();

    public Customer? SelectedCustomer { get; set; }

    public Task LoadAsync() {  }
}

MainWindow.xaml

<ListView Grid.Row="1" x:Name="customerListView"
    ItemsSource="{Binding Customers, Mode=OneWay}"
    Bind the SelectedItem property to the SelectedCustomer property in the DataContext:
    `SelectedItem="{Binding SelectedCustomer, Mode=TwoWay}"`
    DisplayMemberPath="FirstName"
    ScrollViewer.HorizontalScrollMode="Enabled"
    ScrollViewer.HorizontalScrollBarVisibility="Auto"/>

    <!-- Customer detail --->
    <StackPanel Grid.Row="1" Grid.Column="1" Margin="10">
        The Text property is bound to the FirstName property of the SelectedCustomer:
        <TextBox Header="Firstname" Text="`{Binding SelectedCustomer.FirstName, Mode=TwoWay}`"/>
        <TextBox Header="Lastname" Margin="0 10 0 0"/>
        <CheckBox Margin="0 20 0 0">
            Is developer
        </CheckBox>
    </StackPanel>