I've three Classes in my project Master, Person and Command. Master has two properties, a constructor and overridden the ToString:
class Master {
public string FirstName { get; set; }
public string LastName { get; set; }
public Master(string FirstName, string LastName) {
this.FirstName = FirstName;
this.LastName = LastName;
}
public override string ToString() {
return FirstName + " " + LastName;
}
}
Command is an implementation of ICommand
class Command : ICommand {
Func<object, bool> CanDo { get; set; }
Action<object> Do { get; set; }
public event EventHandler CanExecuteChanged;
public Command(Func<object, bool> CanDo, Action<object> Do) {
this.CanDo = CanDo;
this.Do = Do;
CommandManager.RequerySuggested += (o, e) => Evaluate();
}
public bool CanExecute(object parameter) => CanDo(parameter);
public void Execute(object parameter) => Do(parameter);
public void Evaluate() => CanExecuteChanged?.Invoke(null, EventArgs.Empty);
}
and Person has two properties, implemented INotifyPropertyChanged, is an ObservableCollection<Master> and using Command:
class Person : ObservableCollection<Master>, INotifyPropertyChanged {
string firstName, lastName;
public string FirstName {
get => firstName;
set { firstName = value; OnPropertyChanged(); }
}
public string LastName {
get => lastName;
set { lastName = value; OnPropertyChanged(); }
}
public Command AddToList { get; set; }
public new event PropertyChangedEventHandler PropertyChanged;
public Person() {
AddToList = new Command(CanDo, Do);
}
void OnPropertyChanged([CallerMemberName] string name = "") => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
bool CanDo(object para) => !string.IsNullOrEmpty(firstName) && !string.IsNullOrEmpty(lastName);
void Do(object para) {
Add(new Master(firstName, firstName));
FirstName = LastName = null;
}
}
On xaml I've these:
<Window ...>
<Window.Resources>
<local:Person x:Key="Person"/>
</Window.Resources>
<Grid DataContext="{StaticResource Person}">
<StackPanel>
<TextBox Text="{Binding FirstName}"/>
<TextBox Text="{Binding LastName}"/>
<Button Content="Click" Command="{Binding AddToList}"/>
<ListView ItemsSource="{Binding}"/>
</StackPanel>
</Grid>
</Window>
I've to click on the first TextBox, bound to FirstName, after launching the app to type something there, by pressing Tab I can type in the second TextBox and if I then hit Tab again, it instead of focusing the Button goes back to first TextBox so I've to hit Tab twice to get to the Button and by hitting Enter or Space I can add the item in the ListView.
At this point I'm not sure what's focused, I've to hit Tab once more to get to the first TextBox. After typing some more text in first as well as second TextBoxes if I hit Tab, it instead of focusing Button or first TextBox selects the ListView so I've to hit Tab thrice to get to the Button!
I want to give first TextBox focus when the app launches and after hitting Tab on second TextBox I want it to go to the Button and exclude ListView from focus. I've tried setting Focusable="False", KeyboardNavigation.IsTabStop="False", IsTabStop="False" in ListView but those don't work! I also have tried settingTabIndex on TextBoxes and Button like this:
<TextBox Text="{Binding FirstName}" TabIndex="1"/>
<TextBox Text="{Binding LastName}" TabIndex="2"/>
<Button Content="Click" Command="{Binding AddToList}" TabIndex="3"/>
These don't work either!