对用户点击已经选择的ListViewItem, MVVM做出反应

本文关键字:MVVM ListViewItem 用户 选择 | 更新日期: 2023-09-27 18:19:01

我有一个ListView,看起来像这样,它控制在我的应用程序中打开哪个选项卡。

<ListView Grid.ColumnSpan="2" Grid.Row="1" SelectedItem="{Binding Path=SelectedSubstanceName}" Name="listView" ItemsSource="{Binding Path=Substances}" HorizontalAlignment="Stretch" Margin="2" VerticalAlignment="Stretch">
    <ListView.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Lägg till" Command="{Binding AddSubstanceCommand}"/>
            <MenuItem Header="Ta bort" Command="{Binding RemoveSubstanceCommand}"/>
        </ContextMenu>
    </ListView.ContextMenu>
    <ListView.ItemTemplate>
        <DataTemplate>
             <WrapPanel>
                  <TextBlock Text="{Binding Name}" FontWeight="Bold" />
             </WrapPanel>
       </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

我使用selectedsubstanename属性来检测打开哪个选项卡,或者切换到哪个选项卡,如果它已经打开了。

属性如下所示:

private SubstanceName selectedSubstanceName;
public SubstanceName SelectedSubstanceName
{
    get
    {
        return selectedSubstanceName;
    }
    set
    {
        selectedSubstanceName = value;
        OnPropertyChanged("SelectedSubstanceName");
        if (selectedSubstanceName != null)
        {
            if (!Tabs.Any(t => t.Identify(selectedSubstanceName.SubstanceNameID, typeof(SubstanceTabsViewModel))))
                AddTab(selectedSubstanceName);
            else
                SelectedTab = Tabs.First(t => t.Identify(selectedSubstanceName.SubstanceNameID, typeof(SubstanceTabsViewModel)));
        }
    }
}

我无法涵盖的情况是,当用户点击"someessubstance"时,相应的选项卡被打开,用户关闭它,"someessubstance"仍然被选中。如果用户想再次打开它,他必须选择一些其他物质(然后将被打开),然后再次点击"someessubstance"。是否有可能触发属性,甚至当点击相同的ListViewItem?

我知道我可以在双击时添加事件,但理想情况下,我希望避免事件和双击。

对用户点击已经选择的ListViewItem, MVVM做出反应

我认为问题是,在第一次点击一个项目后,列表的SelectedItem得到设置。在第二次单击相同的项目后,SelectedItem不会改变,因为它已经设置为该项目。您应该做的是在处理点击后将SelectedItem设置为null

尝试在选项卡关闭后取消选择ListView中的所有项目。

YOURLISTVIEW.UnselectAll();

因此,下一次有人选择一个项目时,将会有一个变化。

您实际上不想使用ListView类,而是简单地使用ItemsControl,因为它是表示元素序列的最基本方式,但没有额外的SelectedItem, SelectedValue等,任何从Selector派生的类都有。

从那里,它只是一个如何表示ItemsControl中的每个项目的问题。您想要的行为是知道特定项目何时被单击,这将使Button类成为一个很好的候选者,因为它通过ICommand接口处理单击行为。显然,既然您了解DataTemplate s和样式,那么您应该已经知道可以自定义按钮的外观(视觉上),而不会牺牲实际行为(点击处理)。
<ItemsControl ItemsSource="{Binding Path=Substances}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
             <Button Style="{StaticResource SomeStyleToChangeItsLook}"
                     Command="{Binding Path=SelectSubstanceCommand}"
                     CommandParameter="{Binding}"
                     Content="{Binding Path=Name}" />
       </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
public ICommand SelectSubstanceCommand { get; private set; }
private void SelectSubstance(object parameter)
{
    // Add the substance that was "clicked" on here however you want to do it.
}

请记住,我不知道你在使用什么框架,所以我只是给出了一个通用的例子,说明Command代码在视图模型中可能是什么样子的。MVVM和使用wpf出色UI的关键在于始终考虑您想要的行为以及哪些控件提供该行为。忽略它们的实际外观,因为这可以在不失去其行为的情况下进行更改。