ListBoxItem触发器.OnSelectionChanged事件处理程序中的退出行为

本文关键字:退出 程序 触发器 OnSelectionChanged 事件处理 ListBoxItem | 更新日期: 2023-09-27 18:14:35

我有一个包含5个项目(年份)的ListBox。当用户选择最后一项时,我想将列表框项向前移动一年,但保留用户单击的年份的选择:

2011 2012 2013 2014 2015应转为2012 2013 2014 2015 2016。

我是通过搞乱底层ViewModels来做到这一点的:

private void Calendar_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (_calendarUpdateInProgress) return;
        _calendarUpdateInProgress = true;
    var cvm = YearsListBox.SelectedItem as CalendarElementViewModel;
    if (cvm != null)
    {
        int year = cvm.Year; //year I would like to keep selected
        VM.ShiftYear(year);  //change year properties of viewmodels in ItemsSource
        YearsListBox.UnselectAll();
        foreach (CalendarElementViewModel item in YearsListBox.Items)
        {
            if (item.Year == year)
            {
                YearsListBox.SelectedItem = item;
                break;
            }
        }
    }
}

我现在得到的是2012 2013 2014 20152016,似乎这个ListBoxItem样式触发器不会在取消选择时触发:

<Trigger Property="IsSelected" Value="True">
  <Trigger.EnterActions>
      <BeginStoryboard Storyboard="{StaticResource OnSelected}" />
  </Trigger.EnterActions>
  <Trigger.ExitActions>
      <BeginStoryboard Storyboard="{StaticResource OnUnSelected}" />
  </Trigger.ExitActions>
</Trigger>

YearsListBox有一个实际选中的项目(2015),正如预期的那样。我试着跟踪ListBoxItem Selected和Unselected事件-它们也以正确的顺序发射。当我尝试更改非边界项之间的选择时,它们被正确地取消选择。这里发生了什么,为什么最后一项没有正确更新?是因为我正在改变选择,而已经在OnSelectionChanged?

ListBoxItem触发器.OnSelectionChanged事件处理程序中的退出行为

改变视图模型的值使事情变得复杂,它需要你移动你的选择,这也会触发选择再次改变。

试试这样写:

private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    ListBox listBox = sender as ListBox;
    if (listBox.SelectedIndex == this.YearListBox.Count - 1)
    {
        this.YearListBox.Add(new CalendarElementViewModel() { Year = this.YearListBox.Last().Year + 1 });
        this.YearListBox.RemoveAt(0);
    }
}

也可以使用列表框项的可见性属性来隐藏年份

在编写最小代码示例时,我注意到默认样式的ListBoxItem不会表现出这样的行为。不同之处在于处理选择状态的方式,我使用的方式是通过<Trigger Property="IsSelected">和它的触发器。ExitAction不会触发

默认ListBoxItem使用VisualStateManager,它在我的情况下正确工作。虽然这不是我最初问题的答案,但它是一个足够好的变通方法。