单击未选中的listviewitem中的按钮并获取所选项目

时间:2015-04-22 23:42:03

标签: c# wpf listview mvvm

我对listview设置有疑问,如下例所示。当我在扩展器标题中单击下面的按钮时,我也想要选择该项目,但是我看到的是当按钮命令工作时,所选项目仍然是选择的上一个项目,而不是项目my按钮是否处于。如何在单击按钮时选择项目?

我尝试像这样设置一个ControlTemplate,但它没有用。

<Style TargetType="{x:Type ListViewItem}">
    <Setter Property="HorizontalContentAlignment" Value="Stretch" />
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type ListViewItem}">
                    <ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsKeyboardFocusWithin" Value="True">
                            <Setter Property="IsSelected" Value="True" />
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>


<ListView ItemsSource="{Binding MyItemSource,
                                        Mode=TwoWay}"
                  SelectedItem="{Binding MySelectedItem,
                                         Mode=TwoWay}">
    <ListView.ItemTemplate>
        <DataTemplate>
            <Expander IsExpanded="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListViewItem}}, Path=IsSelected}">
                <Expander.Header>
                    <Button Command={Binding MyCommand}>Click Me</Button>
                </Expander.Header>
                <!-- content here -->
            </Expander>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

2 个答案:

答案 0 :(得分:1)

我建议在主ViewModel中定义一个命令SelectItem,该命令将选择作为参数的项目。然后,此命令的执行方法可以设置MySelectedItem属性,将项目ViewModel上的属性IsSelected设置为true,并调用项目本身的所有进一步操作(即现在执行的内容)由MyCommand)。使用ViewModel中的选择逻辑和干净的绑定,您根本不需要使用ListView,但可以坚持使用ItemsControl

然后XAML看起来像这样:

<ItemsControl ItemsSource="{Binding MyItemSource}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Expander IsExpanded="{Binding IsSelected}">
                <Expander.Header>
                    <Button Command="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ItemsControl}, Path=DataContext.SelectItem}"
                            CommandParameter="{Binding"}>Click Me</Button>
                </Expander.Header>
                <!-- content here -->
            </Expander>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

MainViewModel看起来像这样:

public class MainViewModel : INotifyPropertyChanged
{
    public ObservableCollection<ItemViewModel> MyItemsSource { get; private set; }

    public ItemViewModel SelectedItem { get... set... }

    public ICommand SelectItem { get; private set; }

    ctor()...

    private void ExecuteSelectItem(ItemViewModel item)
    {
        SelectedItem = item;
        foreach (var i in MyItemsSource) i.IsSelected = false;
        item.IsSelected = true;
        item.DoSomething();
    }
}

我总是发现自己更容易使用ItemsControl一个实现少数几行选择逻辑的方法,而不是处理ListView选择的混乱绑定。在我看来,实现自定义选择行为(多个项目,仅允许某些组合等)非常直观。您可以轻松使用IsSelected属性来应用所选项目的自定义样式。

答案 1 :(得分:0)

你可以在你的视图模型中尝试这样的东西,在setter中添加if语句:

private object _mySelectedItem;
    public object MySelectedItem
    {
        get { return _mySelectedItem; }
        set 
        {
            if (_mySelectedItem != value && value != null)
            {
                _mySelectedItem = value;
                OnPropertyChanged("MySelectedItem");
            }
        }
    }