У меня есть ListBox с пользовательским шаблоном данных, который содержит CheckBox, TextBlock и TextBox. Обычно, когда вы выбираете элемент в ListBox, базовый ListBoxItem фактически является тем, что имеет фокус, и, как таковой, он реагирует на клавиши вверх и вниз. Кроме того, если у CheckBox есть фокус, так как он сам ничего не делает с клавишами вверх и вниз, он просто счастливо игнорирует их, и они также обрабатываются базовым ListBoxItem. Пока все хорошо.
Однако TextBox имеет свои собственные правила обработки для клавиш «вверх» и «вниз», именуя перемещение курсора вверх или вниз на строку в тексте, что здесь не применимо, потому что в данном случае это одна строка (на самом деле это число) . Таким образом, если TextBox имеет фокус, клавиши «вверх» и «вниз» нарушают навигацию выбора ListBox, а также не помогают при редактировании.
Теперь, хотя я мог бы обрабатывать PreviewKeyDownEvent (что я делаю ниже, но по разным причинам) и вручную обрабатывать поведение в зависимости от нажатых клавиш, это очень специфическое решение и требует, чтобы элемент управления знал о поведении своего контейнера.
В идеальном мире (и в псевдокоде) я хотел бы просто сказать MyTextBox.KeysToIgnore (Up, Down) или что-то подобное и заставить его делать это просто ... игнорировать эти клавиши, как будто это даже не там. (Опять же, не глотайте, но игнорируйте, чтобы они проходили.)
Но до тех пор вот то, что я придумал, и это, кажется, работает, но выглядит для меня просто так "хакерски" ...
private void PreviewKeyDownHandler(object sender, KeyEventArgs e) {
switch (e.Key){
case Key.Up:
case Key.Down:
case Key.OtherKeyToIgnore
case Key.AndAnother
e.Handled = true;
FrameworkElement target = VisualTreeHelper.GetParent(
e.Source as DependencyObject) as FrameworkElement;
target.RaiseEvent(
new KeyEventArgs(
e.KeyboardDevice,
PresentationSource.FromVisual(target),
0,
e.Key
){
RoutedEvent=Keyboard.KeyDownEvent
}
);
break;
}
}
Это также имеет добавленный минус: не отправлять событие PreviewKeyDown цели. Теперь я мог бы обойти это и подделать, отправив сначала это событие, а затем посмотрев на e.Handled перед отправкой фактического сообщения KeyDown, что имеет смысл, но затем я ударил другую стену событиями PreviewKeyUp и KeyUp, поскольку благодаря установке Обращенный выше, я никогда не получаю настоящие события 'key up', чтобы знать, когда отправлять фальшивые. Кроме того, я почти уверен, что нарушу направление сообщений PreviewKeyxxx, поскольку они всплывают в противоположном направлении от обычных версий без предварительного просмотра. (Может быть, это решается внутренне, но я так не думаю.)
Как я уже сказал ... хаки, хаки, хаки!
Но это работает, так что есть это. И я могу реализовать это через Attached Behaviors, поэтому я даже пошел по этому пути. (В реализации присоединенного поведения это не оператор case, а скорее проверка набора ключей, который я указываю в XAML.) Мне просто не нравится идея потерять все другие поведения, которые я хочу.
Опять же, я просто хочу сказать: «Привет, TextBox ... когда вы видите нажатие клавиш« Вверх »или« Вниз », STFU ya b * stard !! ' а в противном случае сделайте его прозрачным для ключа.
Кто-нибудь думает?