【问题标题】:ItemsControl inside Popup duplicates the first item addedPopup 中的 ItemsControl 复制了添加的第一个项目
【发布时间】:2018-09-06 12:01:33
【问题描述】:

我在Popup 中有一个ItemsControl 和一个ObservableCollection,我将其简称为“集合”,绑定到ItemsControl.ItemsSource 属性。

ItemsControl 将始终复制添加到集合中的第一个项目。然后ItemsControl 会正确处理之后添加的每个项目。

  • 没有发生跨线程操作。
  • 集合仅在一个地方更新,每个项目创建一个调用。
  • ItemsControl.ItemsPanel 是一个没有虚拟化的StackPanel

I found a similar question。但是,建议的解决方案并没有解决我的问题。

我有一种预感,这是由于在 Popup 中使用了 ItemsControl,但我无法弄清楚为什么会发生这种情况,并且只能使用第一项。

有什么建议吗?

编辑:

集合在单独的单例类中更新。在初始化我的视图和视图模型时,我创建了一个本地集合,引用了单例中的集合。我可以确认没有重复的项目添加到集合中,并且它的行为正确。

这里是一些示例代码:

XAML:

<Popup IsOpen="{Binding ShowNotifications, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
       StaysOpen="True"
       AllowsTransparency="True">

    <ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">

        <ItemsControl ItemsSource="{Binding AlarmNotifications}">

            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>

                    <StackPanel/>

                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>

            <ItemsControl.ItemTemplate>
                <DataTemplate>

                     <TextBlock Text="{Binding Exception.Message}"/>

                </DataTemplate>
            </ItemsControl.ItemTemplate>

        </ItemsControl>

    </ScrollViewer>

</Popup>

C# 视图模型

public ManagerClass Manager { get; set; }

public ObservableCollection<AlarmRegistry> AlarmNotifications { get; set; }

public bool ShowAlarmNotifications => AlarmNotifications.Any();

protected MainViewModel()
    {
        Manager = ManagerClass.Instance;

        AlarmNotifications = Manager.AlarmNotifications;

        AlarmNotifications.CollectionChanged += (sender, args) =>
        {
            OnPropertyChanged(nameof(ShowAlarmNotifications));
        };
    }

更新:

我发现了两种纠正重复的方法,即在添加第一项之前打开弹出窗口:

  1. 删除 Popup.IsOpen 绑定并在 XAML 中将其设置为 true。
  2. ShowNotifications 的默认值设置为true。

这些方法会导致应用程序在弹出窗口打开时启动,这是一种不受欢迎的行为。但是,这会阻止 ItemsControl 复制添加的第一个项目。如果在添加第一项之前再次关闭 Popup,则不会发生重复。

现在我正在寻找一种方法来保持弹出窗口在启动时关闭,而不会重复第一个项目。一种方法是试图诱使弹出窗口在之后立即打开和关闭。

如果您知道为什么会发生这种情况,或者如何应对,请告诉我。

【问题讨论】:

  • “ItemsControl 将始终复制添加到集合中的第一个项目。”...我从未在手册中阅读过它,它究竟是什么意思?添加所需的数据以使其清晰!
  • 什么不清楚?我将单个项目添加到绑定到 ItemsControl 的 ObservableCollection 中,并且该项目在 UI 中显示两次。这种情况始终如一,但仅适用于会话中添加的第一项。
  • 所以你说当你在有界集合上添加一个新项目时,弹出窗口(我想是组合框的)在两行中向你显示该项目。如果是这样,某处应该有一个错误。发布示例代码以重现此行为以获得帮助并找到更正
  • 我希望某处存在错误,但由于代码如此简单,我无法理解为什么会发生这种情况。除非弹出窗口涉及一些奇怪的行为,正如我在类似问题的链接中所指出的那样。
  • 默认情况下,BindingMode 是 OneTime,您可能会看到将其设置为 OneWay 时会发生什么,它会在集合更改时刷新绑定的 UI。

标签: wpf xaml itemscontrol


【解决方案1】:

我最近遇到了同样的问题。我按照AllowsTransparency="True" IsOpen="True" 的顺序修复了它。出于某种原因,如果您首先指定IsOpen,则透明度不起作用。另请注意,IsOpen 设置为始终为真。这解决了我的重复问题和透明度问题。希望有帮助。

<Popup AllowsTransparency="True" IsOpen="True">
    <!--your content goes here-->
</Popup>

【讨论】:

    【解决方案2】:

    如果在将第一项添加到集合之前未打开 Popup,则会发生重复。

    为了纠正这个问题,分为三个步骤:

    1. ShowAlarmNotifications 属性添加一个setter 和,以便可以直接设置它并更新用法:

      private bool _showAlarmNotifications;
      
      
      public bool ShowAlarmNotifications
      {
          get => _showAlarmNotifications;
          set
          {
              _showAlarmNotifications = value;
              OnPropertyChanged();
          }
      }
      
      
      AlarmNotifications.CollectionChanged += (sender, args) =>
      {
          ShowAlarmNotifications = AlarmNotifications.Any();
      };
      
    2. 为视图创建一个Loaded 事件并将ShowAlarmNotifications 设置为true

      private void View_OnLoaded(object sender, RoutedEventArgs e)
      {
          if (DataContext is ViewModel vm)
              vm.ShowAlarmNotifications = true;
      }
      
    3. 为 Popup 创建一个Loaded 事件并将ShowAlarmNotifications 设置为false

      private void Popup_OnLoaded(object sender, RoutedEventArgs e)
      {
          if (DataContext is ViewModel vm)
              vm.ShowAlarmNotifications = false;
      }
      

    ItemsControl 不再重复第一个条目,并且Popup 在应用程序启动时未打开。

    这是一个混乱的解决方案,仍然没有解释为什么会发生重复,但它确实满足要求。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多