ItemsControl внутри Popup дублирует первый добавленный элемент - PullRequest
0 голосов
/ 06 сентября 2018

У меня есть ItemsControl внутри Popup с ObservableCollection, который я буду называть просто 'Collection', привязанным к свойству ItemsControl.ItemsSource.

ItemsControl всегда будет дублировать первый элемент, добавленный в коллекцию. ItemsControl затем ведет себя корректно для каждого добавленного элемента.

  • Операции с перекрестными потоками не выполняются.
  • Коллекция обновляется только в одном месте, при этом создается один вызов для каждого элемента.
  • ItemsControl.ItemsPanel - это StackPanel без виртуализации.

Я нашел похожий вопрос . Однако предлагаемое решение не решило мою проблему.

У меня есть предчувствие, что я использую ItemsControl внутри Popup, но я не могу понять, почему это происходит, и только с первым элементом.

Есть предложения?

EDIT:

Коллекция обновляется в отдельном синглтон-классе. При инициализации моей View & ViewModel я создаю локальную коллекцию, ссылающуюся на коллекцию в синглтоне. Я могу подтвердить, что в Коллекцию не добавлены повторяющиеся элементы, и она ведет себя правильно.

Вот пример кода:

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 # View-Model :

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));
        };
    }

UPDATE:

Я нашел два подхода, которые исправляют дублирование, которое включает в себя открытие всплывающего окна перед добавлением первого элемента:

  1. Снятие привязки Popup.IsOpen и установка в XAML значения true.
  2. Установка значения по умолчанию ShowNotifications в true.

Эти подходы приводят к тому, что приложение запускается с открытым Popup, что является нежелательным поведением. Однако это останавливает ItemsControl, дублирующий первый добавленный элемент. Если всплывающее окно снова закрывается до добавления первого элемента, дублирование не происходит.

Теперь я ищу способ сохранить всплывающее окно закрытым при запуске без дублирования первого элемента. Один из подходов - попытаться заставить Popup открываться и закрываться сразу после.

Если вы знаете, почему это происходит или как с этим бороться, пожалуйста, дайте мне знать.

Ответы [ 2 ]

0 голосов
/ 21 ноября 2018

Я недавно столкнулся с той же проблемой.Я исправил это, выполнив это в порядке AllowsTransparency="True" IsOpen="True".По какой-то причине, если вы сначала укажете IsOpen, прозрачность не будет работать.Также обратите внимание, что IsOpen всегда имеет значение true.Это решило мою проблему дублирования и проблему прозрачности.Надеюсь, это поможет.

<Popup AllowsTransparency="True" IsOpen="True">
    <!--your content goes here-->
</Popup>
0 голосов
/ 06 сентября 2018

Дублирование происходит, если всплывающее окно не открывается до добавления первого элемента в коллекцию.

Чтобы исправить проблему, было три шага:

  1. Добавьте установщик и к свойству ShowAlarmNotifications, чтобы его можно было установить напрямую, и обновите использование:

    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. Создайте событие Loaded для всплывающего окна и установите ShowAlarmNotifications на false:

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

ItemsControl больше не дублирует первую запись, а Popup не открывается при запуске приложения.

Это грязное решение, которое до сих пор не объясняет, почему происходит дублирование, но оно удовлетворяет требованиям.

...