3

Есть

<ListView ItemsSource="{Binding StudentsList}" SelectedItem="{Binding SelectedStudent}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel Margin="10">
                <TextBlock Text="{Binding}" FontWeight="Bold"/>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="{Binding GetGroupNum}" Margin="10,0"/>
                </StackPanel>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

Где StudentList - коллекция студентов, SelectedStudent - конкретный выбранный студент.

Необходимо по двойному нажатию на ListView, вызвать команду EditStudent. Команды умею привязывать только к Button. Как поступить в этом случае?

TorSen
  • 468

3 Answers3

5

Давайте воспользуемся такой штукой как InputBindings:

<StackPanel>
    <StackPanel.InputBindings>
        <MouseBinding Gesture="LeftDoubleClick"
                      Command="{Binding DataContext.EditStudent,
                          RelativeSource={RelativeSource FindAncestor,
                              AncestorType=Window}}"
                      CommandParameter="{Binding}"/>
    </StackPanel.InputBindings>
    ...
</StackPanel>

Это уже работает, но у всех ItemsControl есть нюанс - по умолчанию они не растягивают свои элементы, это можно увидеть, если задать StackPanel любой цвет в Background, поэтому команда будет вызываться только при клике четко по тексту элемента. Исправить это можно, подкорректировав стиль ListViewItem:

<ListView ItemsSource="{Binding StudentsList}" ...>
    <ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
            <Setter Property="VerticalContentAlignment" Value="Stretch"/>
        </Style>
    </ListView.ItemContainerStyle>
...

Ну и нужно еще что-то сделать с отступами, так как то что у вас сейчас StackPanel Margin="10" вам скорее всего не понравится, например можно обернуть всё в прозрачный Border (InputBindings теперь переезжают в него, в StackPanel они больше не нужны):

<ListView.ItemTemplate>
    <DataTemplate>
        <Border Padding="10">
            <Border.InputBindings>
                <MouseBinding Gesture="LeftDoubleClick"
                              Command="{Binding DataContext.EditStudent,
                                  RelativeSource={RelativeSource FindAncestor,
                                      AncestorType=Window}}"
                              CommandParameter="{Binding}"/>
            </Border.InputBindings>
            <StackPanel>
                ...
            </StackPanel>
        </Border>
    </DataTemplate>
</ListView.ItemTemplate>

Вот тогда между элементами будут визуальные отступы, но команда будет отрабатывать по клику в любом месте элемента

  • Да, Ваш вариант подходит, именно то, что и хотел. Спасибо. – TorSen Oct 25 '17 at 09:45
  • MouseBinding? Круто, не знал, пользовался System.Interactivity вместо этого. – VladD Oct 25 '17 at 12:53
  • @VladD, фишка в том еще, что у StackPanel нет события DoubleClick вообще, поэтому Interactivity не понятно как привязать – Андрей NOP Oct 25 '17 at 13:01
  • @Андрей: Например, на MouseLeftButtonUp, как здесь. – VladD Oct 25 '17 at 22:51
  • @VladD, а количество кликов и время задержки между ними вручную подсчитывать что ли? – Андрей NOP Oct 26 '17 at 03:13
  • @VladD, кстати, у MouseBinding еще преимущество в том, что можно клавишу-модификатор прямо в разметке указать, типа Gesture="Alt+MiddleClick": https://msdn.microsoft.com/ru-ru/library/system.windows.input.mousebinding.gesture(v=vs.110).aspx – Андрей NOP Oct 26 '17 at 07:00
  • Хм, и правда, DoubleClick есть только у контролов https://msdn.microsoft.com/ru-ru/library/system.windows.controls.control.mousedoubleclick(v=vs.110).aspx. То есть пришлось бы навешивать на весь ListView. Но да, это дополнительный геморрой, и может не прокатить в общем случае. Бесспорно, нативный MouseBinding должен быть удобнее. – VladD Oct 26 '17 at 07:10
0
    private void ListView_MouseDoubleClick_1(object sender, MouseButtonEventArgs e)
    {
        EditStudent();
    }  
  1. Выделите listview в конструкторе;
  2. Перейдите во вкладку "свойства";
  3. Кликните на кнопку с картинкой молнии в верхнем правом углу, ее название "Обработчики событий выбранного элемента", в разных студиях может называться по разному;
  4. Найдите событие с именем MouseDoubleClick, в пустое поле кликните 2 раза и студия все сделает за Вас;
    введите сюда описание изображения
0
<ListView>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseDoubleClick">
            <i:InvokeCommandAction Command="{Binding EditStudent}" CommandParameter=""/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ListView>
Gardes
  • 3,358
  • Это клик по самому ListView, а ТС надо клик по элементу, не так ли? Можно кликнуть 2 раза в любом месте ListView и это событие сработает, даже если в нем нет ни одного элемента – Андрей NOP Oct 25 '17 at 05:31
  • 2
    Дождемся автора чтобы разрешить эту дилемму – Gardes Oct 25 '17 at 05:35
  • Клик необходим по элементу. Команда во ViewModel. – TorSen Oct 25 '17 at 09:39