如何在模板中点击按钮时选择ListBoxItem? [英] How to select ListBoxItem upon clicking on button in Template?

查看:417
本文介绍了如何在模板中点击按钮时选择ListBoxItem?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下数据模板应用于ListBox:

I have the following Data Template applied to a ListBox:

<DataTemplate x:Key="MyTemplate" DataType="{x:Type DAL:Person}">
    <StackPanel Orientation="Horizontal">
        <Button Content="X" Command="{x:Static cmd:MyCommands.Remove}"/>
        <TextBlock Text="{Binding Person.FullName}" />
    </StackPanel>
</DataTemplate>

当我点击按钮时,命令被触发,但ListBoxItem没有被选中。如何强制它被选择,以便我可以在我的执行方法中获得所选项目?

When I click on the button the command gets fired but the ListBoxItem doesn't get selected. How do I force it to get selected, so that I can get the selected item in my "executed" method?

感谢

推荐答案

真正有兴趣选择项目(因为它很快会被删除)将作为CommandParameter传递给命令本身。

A better way, since you're not really interested in selecting the item (because it will quickly get deleted anyway) would be to pass the item itself to the Command as a CommandParameter.

或者,你可以去在迂回的方式与代码隐藏或与触发器,但我不认为这将是至关重要。例如:

Alternatively, you can go about in a roundabout manner either with code-behind or with triggers, but I don't think it would be as to the point. For example:

您可以处理列表框上的ButtonBase.Click事件,例如

you could handle the ButtonBase.Click event on your listbox, like

<ListBox ButtonBase.Click="lb_Click"
...

然后在您的代码中,执行以下操作:

then in your code behind, do this:

private void lb_Click(object sender, RoutedEventArgs e)
{
    object clicked = (e.OriginalSource as FrameworkElement).DataContext;
    var lbi = lb.ItemContainerGenerator.ContainerFromItem(clicked) as ListBoxItem;
    lbi.IsSelected = true;
}

获得被点击的绑定项,因为按钮的数据文字继承自它是模板项,然后是从ListBox的ItemContainerGenerator实际自动生成的ListBoxItem,并将IsSelected属性设置为true。我认为这是最快和最简单的方法之一。也可以在模板中使用多个ButtonBase派生的对象。

That gets the clicked bound item, because the datacontext of the button is inherited from it's templated item, then the actual autogenerated ListBoxItem from the ListBox's ItemContainerGenerator, and sets the IsSelected property to true. I think that's one of the fastest and easiest ways. Also works with multiple ButtonBase-derived objects in the template.

当然你也可以更好地封装所有这些(或多或少完全相同) href =http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx =nofollow noreferrer>行为:

Of course you can also more nicely encapsulate all this (more or less exactly the same) as a reusable Behavior:

public class SelectItemOnButtonClick : Behavior<ListBox>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.AddHandler(ButtonBase.ClickEvent, new RoutedEventHandler(handler), true);
    }
    protected override void OnDetaching()
    {
        this.AssociatedObject.RemoveHandler(ButtonBase.ClickEvent, new RoutedEventHandler(handler));
        base.OnDetaching();
    }
    private void handler(object s, RoutedEventArgs e)
    {
        object clicked = (e.OriginalSource as FrameworkElement).DataContext;
        var lbi = AssociatedObject.ItemContainerGenerator.ContainerFromItem(clicked) as ListBoxItem;
        lbi.IsSelected = true;
    }
}

您可以这样使用:

<ListBox xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" ...>
    <i:Interaction.Behaviors>
        <local:SelectItemOnButtonClick />
    </i:Interaction.Behaviors>
</ListBox>

添加错误处理代码,如至少null检查,当然 - 不想要一个简单的事情这会轰炸你的应用程序。

Add error handling code like at least null checks, of course - wouldn't want a simple thing like this bombing your app.

为了理解这个问题,按钮将Handled属性设置为true为所有鼠标事件(鼠标下/点击) ListBoxItem正在考虑。你还可以将MouseDown事件附加到ListBox并向上走动视觉树,直到到达父ListBoxItem,但这是一个更棘手的...如果你好奇,你可以阅读这篇文章知道为什么,基本上你还会遇到FrameworkContentElements(它也响应MouseDown),所以代码将获得更复杂的是,无论是否将事件标记为已处理,在datatemplate内部点击的任何内容都将触发ListBoxItem的选择。

To understand the problem, the button sets the Handled property to true for all the mouse events that act on it (MouseDown/Click) so they aren't being considered by the ListBoxItem. You could also attach the MouseDown event to the ListBox and walk the visual tree upwards until you reach the parent ListBoxItem but that's a lot more tricky... eh if you're curious, you can read this article to know why, basically you'll also encounter FrameworkContentElements (which also respond to MouseDown) so the code will get more complicated, with the upside that anything clicked inside the datatemplate will trigger the ListBoxItem to be selected, regardless of whether it marked the event as handled.

做它专门与风格和触发器,但它丑陋的快,我失去了兴趣(和失去所有的错误轨迹)。基本上,它可以解决,我想,但我reaaaly不认为这是值得的麻烦。也许我忽略了一些明显的东西,但不知道。

Heh, I also tried to do it exclusively with styles and triggers but it got ugly fast and I lost interest (and lost track of all the... err thingies). Basically it could be solved, I think, but I reaaaly don't think it's worth the bother. Maybe I overlooked something obvious though, don't know.

这篇关于如何在模板中点击按钮时选择ListBoxItem?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆