当我们有一个自定义列表框,其中包含鼠标左键单击的已定义事件处理,以及ListBoxItem数据模板中需要在单击时执行某些操作的其他形状,我们如何处理这些
我有一个Custom ListBox女巫试图处理Click事件:
在ContentView中:
<ABC:AListBox
ClickCommand="{Binding LaunchCommand}"
...>
</ABC:AListBox>
在它的datatemplate我们有这个:
<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()
{ ... }
在这里,我使用了两个不同的命令LaunchCommand作为ICommand以及通过模板调用的LaunchFromXamlCommand。
LaunchFromXamlRun
将被触发罚款并按预期进行。但也可以猜到,会有2个引发的事件和2个命令被触发,我想省略一个并忽略一般的ListBox事件处理程序,当该形状被命中时。
这样做的最佳解决方案是什么?
仅供参考:(可能对于一个注释来说可能不那么重要)App正在使用早期版本的Prism(不要认为这里很重要)并且具有模块化代码,所有内容都在不同的程序集中分离,代码使用MVVM模式。
我希望我们在一个可以在给定场景中使用的机制中使用类似e.handled = true
的东西。
在列表框中使用单击处理程序会加剧您的问题。我不知道你是怎么做的,但这不仅仅是点击。它可能是预览的。因为,当然,列表框“吃掉”作为选择项目的一部分。
一种方法是不使用该列表框previewmousedown。在这里,我将行内容放在一个按钮中并绑定按钮的命令。它当然不像一个按钮。
我把圆圈变成了一个按钮并给它一个透明的填充,这样你就可以点击它了。
<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使用relay命令,但(显然)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的原因,因此您单击的项目将通过绑定进行选择。