2016-10-11 3 views
0

Ситуация: В шаблоне MVVM у меня есть некоторые входные имена в списке, которые работают только при сфокусированном виде списка. Тем не менее, всякий раз, когда пользователь щелкает, listview выходит из фокуса, и пользователь не может выполнить входные имена.Невозможно сфокусировать ListView

Задача: Я хочу обратить внимание на список (при нажатии кнопки) таким образом, чтобы операции ввода работали.

Что я пытался: Я попытался использовать прикрепленное свойство IsFocused (где я фокусируюсь с использованием UIElement.Focus() и/или Keyboard.Focus()) и привязывая его к переменной bool в ViewModel, которую я бы установил с помощью ICommand.

Я также попробовал отдельный пример, где я могу использовать метод System.Windows.Input.Keyboard.Focus (item) в коде позади (я имею в виду файл .xaml.cs с тем же именем), чтобы сфокусировать список и это работает! Но я не знаю, как реализовать аналогичную вещь в ViewModel, которая связана с атрибутом d: DesignInstance.

Я считаю, что событие mouseclick пузырится и обрабатывается где-то в другом месте, что заставляет список не фокусироваться, как только я нажимаю на него. Например, если я нахожу способ установить событие как обработанное, что поможет, но опять же я не знаю, как это сделать в viewmodel. Вот мое вложенное свойство:

FocusExtension.cs

public static class FocusExtension { 
    public static bool GetIsFocused(DependencyObject obj) { 
     return (bool)obj.GetValue(IsFocusedProperty); 
    } 

    public static void SetIsFocused(DependencyObject obj, bool value) { 
     obj.SetValue(IsFocusedProperty, value); 
    } 

    public static readonly DependencyProperty IsFocusedProperty = 
     DependencyProperty.RegisterAttached(
      "IsFocused", typeof(bool), typeof(FocusExtension), 
      new UIPropertyMetadata(false, OnIsFocusedPropertyChanged)); 

    private static void OnIsFocusedPropertyChanged(
     DependencyObject d, 
     DependencyPropertyChangedEventArgs e) { 
     var uie = (UIElement)d; 
     if ((bool)e.NewValue) { 
      uie.Focus(); 
     } 
    } 
} 

XAML файл:

<ListView 
     x:Name="lv" 
     Grid.Column="2" Margin="2" MinWidth="250" Height="400" ToolTip="the List" 
     HorizontalContentAlignment="Stretch" 
     ItemsSource="{Binding ListBindingInVM}" 
     ScrollViewer.HorizontalScrollBarVisibility="Auto" 
     ScrollViewer.CanContentScroll="False" 
     dd:DragDrop.IsDragSource="True" 
     dd:DragDrop.IsDropTarget="True" 
     dd:DragDrop.DropHandler="{Binding }" 
     behaviour:ListViewAutoScroll.AutoScrollToEnd="True" 
     ScrollViewer.VerticalScrollBarVisibility="Visible" 
     > 

     <ListView.Style> 
      <Style TargetType="ListView" > 
       <Setter Property="ViewModels:FocusExtension.IsFocused" Value="{Binding ListFocused, Mode=TwoWay}"></Setter> 
       <!--The one below is not clean, but worked. However, list goes out of focus on click. --> 
       <Style.Triggers> 
        <Trigger Property="IsMouseOver" Value="True"> 
         <Setter Property="ViewModels:FocusExtension.IsFocused" Value="True"></Setter> 
        </Trigger> 
       </Style.Triggers> 


      </Style> 
     </ListView.Style> 

     <i:Interaction.Triggers> 
      <i:EventTrigger EventName="MouseDown"> 
      <!--This command sets the ListFocused to true--> 
       <i:InvokeCommandAction Command="{Binding BringListToFocus }"></i:InvokeCommandAction> 
      </i:EventTrigger> 
     </i:Interaction.Triggers> 


     <ListView.InputBindings> 
      <!-- Bindings that don't work when list is not focused--> 
      <KeyBinding Modifiers="Control" Key="C" Command="{Binding CopyCommand}"/> 
      <KeyBinding Modifiers="Control" Key="V" Command="{Binding PasteCommand}"/> 
     </ListView.InputBindings> 

     <ListView.ContextMenu> 
      <ContextMenu> 
       <MenuItem Header="Copy" Command= "{Binding CopyCommand}"></MenuItem> 
       <MenuItem Header="Paste" Command= "{Binding PasteCommand}"></MenuItem> 
      </ContextMenu> 
     </ListView.ContextMenu> 
+2

MVVM! = No codebehind. Это означает, что у вас не будет кода, специфичного для пользовательского интерфейса. Попытка установить фокус в вашей виртуальной машине - это не лучшая идея, как вы нашли. Обратите внимание, если у вас возникли проблемы с событиями, возьмите Snoop. Он будет отслеживать события и сообщать вам, какой элемент блокирует пузырьки. – Will

+0

Спасибо за комментарий :) Я знаю, но «руководящие принципы», над которыми я работаю, хотят, чтобы я не вводил код в код. Использовать snoop будет длительный процесс, поговорить с членами команды и т. Д. Возможно ли иметь какое-либо обходное решение с любым изменением только в xaml и/или, возможно, в viewmodel? – 10101010

+1

Вернитесь к руководству.И Snoop не является «длительным процессом», это приложение, которое показывает вам, что происходит в вашем пользовательском интерфейсе WPF, включая ошибки привязки, распространение событий и другие положительные эффекты. Это отличный инструмент и бесплатный. – Will

ответ

-1

поведение фокуса, что вы описываете легко реализуются с коды, и делать это не нарушает MVVM. Рассмотрим пост Джоша Смита, ниже:

https://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090097

Использование ViewModel здесь делает его гораздо легче создать представление, которое может отображать объект Customer и позволяет такие вещи, как «неотобранной» состояние булевого свойства. Он также предоставляет возможность легко сообщить клиенту о сохранении его состояния. Если представление было привязано к объекту Customer , для представления потребуется много кода , чтобы эта работа работала должным образом. В хорошо продуманной архитектуре MVVM код для большинства представлений должен быть пустым или, самое большее, содержать только код , который управляет элементами управления и ресурсами, содержащимися в этом представлении . Иногда также необходимо написать код в коде View, который взаимодействует с объектом ViewModel, например, подключением события или вызовом метода, который в противном случае был бы очень трудным для вызывать из самой ViewModel.

Смежные вопросы