Обработка того же события щелчка во вложенном элементе управления внутри ListBoxItem DataTemplate - WPF - PullRequest
2 голосов
/ 21 апреля 2019

Когда у нас есть настраиваемый список с определенной обработкой событий для щелчка левой кнопкой мыши, а также дополнительная фигура внутри шаблона данных ListBoxItem, которая должна выполнить какое-то действие при нажатии, как мы можем обработать эти

У меня есть пользовательский ListBox, который пытается обработать событие Click:

В ContentView:

                <ABC:AListBox
                    ClickCommand="{Binding LaunchCommand}"
                    ...>
                </ABC:AListBox>

В его табличке данных мыесть это:

        <DataTemplate x:Key="ThisListTemplate">
            <StackPanel ...>
                <Border Grid.Column="1" VerticalAlignment="Center">
                    <TextBlock
                        FontSize="15"
                        Foreground="White"
                        Text="{Binding Path=ItemTitle}" />      
                </Border>
                <Canvas Height ="12" Width ="12" >
                  <Ellipse Name = "TheEllipse" Stroke="Black" Height ="12"                                  
                           Width ="12" Cursor="Hand" Canvas.Left="185" Canvas.Top="12">                          
                  </Ellipse>
                    <Ellipse.InputBindings>
                        <MouseBinding Gesture="LeftClick"
                                      Command="{Binding DataContext.LaunchFromXamlCommand , RelativeSource={RelativeSource AncestorType=ABC:AListBox}}"
                                      CommandParameter="{Binding}" />
                    </Ellipse.InputBindings>                      
                </Canvas> 
            </StackPanel>                   
        </DataTemplate>

И в MVVM в качестве контекста данных мы имеем:

    public ICommand LaunchCommand { get; private set; }
    public DelegateCommand<object> LaunchFromXamlCommand { get; private set; }

    // Initialization on load:

    this.LaunchCommand = new DelegateCommand(this.LaunchRun);
    this.LaunchFromXamlCommand = new DelegateCommand<object>(this.LaunchFromXamlRun);


    //---------     
    private void LaunchFromXamlRun(object param)
    {
            TheListItem app = (TheListItem)param;   
    ...
    }   

    private void LaunchRun()
    { ... }

Здесь я использовал 2 разные команды LaunchCommand в качествеICommand в дополнение к LaunchFromXamlCommand, который вызывается через шаблон.

LaunchFromXamlRun будет срабатывать нормально и, как и ожидалось.Но также, как можно догадаться, будут вызваны 2 вызванных события и 2 команды, которые я хочу пропустить, и игнорировать общий обработчик событий ListBox при получении этой формы.

Что может быть лучшим решениемдля этого?

К вашему сведению: (Может быть, это не так важно, просто для заметки) Приложение использует более ранние версии Prism (не думаю, что это имеет значение здесь) и имеет модульный код, все разделено на разные сборки, и код использует шаблон MVVM.

Хотелось бы, чтобы у нас было что-то вроде e.handled = true в механизме, который мог бы использоваться в данном сценарии.

1 Ответ

1 голос
/ 21 апреля 2019

Ваша проблема усугубляется наличием этого обработчика кликов в вашем списке. Я не знаю, как ты это делаешь, но это не может быть просто щелчок. Это, вероятно, превью mousedown. Потому что, конечно, список «съедает» mousedown как часть выбора элемента.

Одним из способов решения этой проблемы является отключение предварительного просмотра списка. Здесь я помещаю содержимое строки в кнопку и связываю команду кнопки. Конечно, это не похоже на кнопку.

Я превращаю круг в кнопку и делаю его прозрачным, чтобы вы могли щелкнуть по нему все.

    <ListBox ItemsSource="{Binding People}">
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
            </Style>
        </ListBox.ItemContainerStyle>
        <ListBox.ItemTemplate>
            <DataTemplate>
                <Button  Command="{Binding DataContext.ItemClickCommand, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
                         CommandParameter="{Binding}"
                         >
                    <Button.Template>
                        <ControlTemplate>
                            <StackPanel Orientation="Horizontal">
                                <TextBlock Text="{Binding LastName}"/>
                                <Button Command="{Binding DataContext.EllipseCommand, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}"
                                >
                                    <Button.Template>
                                        <ControlTemplate>
                                            <Ellipse Name = "TheEllipse" Stroke="Black" 
                                         Fill="Transparent"
                                         Height ="12"                                  
                                         Width="12" Cursor="Hand">
                                            </Ellipse>
                                        </ControlTemplate>
                                    </Button.Template>
                                </Button>

                            </StackPanel>
                        </ControlTemplate>
                    </Button.Template>
                </Button>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

Моя viewmodel использует relaycommands, но (очевидно) подойдет любая реализация ICommand. У меня были Люди из последнего вопроса, над которым я работал.

public class MainWindowViewModel : BaseViewModel
{
    private RelayCommand ellipseCommand;
    public RelayCommand EllipseCommand
    {
        get
        {
            return ellipseCommand
            ?? (ellipseCommand = new RelayCommand(
              () =>
             {
                 Console.WriteLine("CIRCLE clicked");
             }
             ));
        }
    }
    private RelayCommand<Person> itemClickCommand;
    public RelayCommand<Person> ItemClickCommand
    {
        get
        {
            return itemClickCommand
            ?? (itemClickCommand = new RelayCommand<Person>(
              (person) =>
              {
                  Console.WriteLine($"You clicked {person.LastName}");
                  person.IsSelected = true;
              }
             ));
        }
    }
    private ObservableCollection<Person> people = new ObservableCollection<Person>();

    public ObservableCollection<Person> People
    {
        get { return people; }
        set { people = value; }
    }

    public ListCollectionView LCV { get; set; }
    public MainWindowViewModel()
    {
        People.Add(new Person { FirstName = "Chesney", LastName = "Brown" });
        People.Add(new Person { FirstName = "Gary", LastName = "Windass" });
        People.Add(new Person { FirstName = "Liz", LastName = "McDonald" });
        People.Add(new Person { FirstName = "Carla", LastName = "Connor" });
    }
}

Когда вы нажимаете эту внешнюю кнопку, она захватывает щелчок. Вот почему я установил IsSelected в команде, чтобы элемент, по которому вы щелкаете, выбирался с помощью привязки.

...