-1

I have an ItemsControl inside a Popup with an ObservableCollection, which I'll refer to as simply 'Collection', bound to the ItemsControl.ItemsSource property.

The ItemsControl will always duplicate the first item added to the Collection. The ItemsControl then behaves correctly for every item added thereafter.

  • There are no cross-thread operations taking place.
  • The Collection is only updated in one place, with one call per item created.
  • The ItemsControl.ItemsPanel is a StackPanel with no virtualization.

I found a similar question. However, the proposed solution did not solve my issue.

I have a hunch that is due to using the ItemsControl inside a Popup but I can't figure out why this is happening, and only with the first item.

Any suggestions?

EDIT:

The Collection is updated in a separate singleton class. On Initialization of my View & ViewModel I create a local Collection referencing the one within the singleton. I can confirm that there are no duplicate items added to the Collection and that it does behave correctly.

Here is some sample code:

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:

I found two approaches which correct the duplication which involve opening the Popup before the first item is added:

  1. Removing the Popup.IsOpen binding and setting it to true in XAML.
  2. Setting the default value of ShowNotifications to true.

These approaches cause the application to start with the Popup open, which is an undesired behavior. However, this stops the ItemsControl duplicating the first item added. If the Popup is closed again before the first item is added, the duplication does not occur.

Now I am searching for a way to keep the Popup closed at start-up without having the first item duplicated. One approach would be trying to trick the Popup into opening and closing immediately after.

If you know why this happens, or how to counter it, please let me know.

Jack
  • 886
  • 7
  • 27
  • "The ItemsControl will always duplicate the first item added to the Collection."... I've never read it on the manuals, what does it exactly mean? Add needed data to make it clear!! – Alessandro Rossi Sep 06 '18 at 12:12
  • What's not clear? I add a single item to an ObservableCollection, which is bound to an ItemsControl, and the item is shown twice in the UI. This happens consistently but only for the first item added in the session. – Jack Sep 06 '18 at 12:14
  • So you said that when you add a new item on the bounded collection, the popup (of the combobox I suppose) is showing you that item in two rows. If so there should be a bug somewhere. Post sample code to reproduce this behavior to get help and find the correction then – Alessandro Rossi Sep 06 '18 at 12:20
  • I would expect there to be a bug somewhere, but with the code as simple as it is I cannot fathom why this is happening. Unless there is some strange behaviour involved with the Popup, as I noted with the link to a similar question. – Jack Sep 06 '18 at 12:27
  • By default BindingMode is OneTime you probably could see what happens when setting it to OneWay witch refreshs the bound UI on collection changes. – Alessandro Rossi Sep 06 '18 at 12:31
  • Thank you for the suggestion, I had not thought to do that. However, the problem persists. – Jack Sep 06 '18 at 12:35
  • Are you sure that there is just one element inside the collection? Use a breakpoint and check it for example in loaded event of the window/usercontrol. – Babbillumpa Sep 06 '18 at 12:55
  • This was my first thought, but it appears there is only a single item in the collection. – Jack Sep 06 '18 at 12:58
  • How many items are there in `Manager.AlarmNotifications` and what's the value of the `Exception.Message` property of these? Your issue is obviously not reproducible based on the information you have provided so I don't know what kind of answer you are expecting. – mm8 Sep 06 '18 at 13:08
  • First, you have to be 100% sure that there is just one element. – Babbillumpa Sep 06 '18 at 13:13
  • At this point I don't think my problem is reproducible at all, just some strange anomaly. At application start the collection is empty, once the first item is added the UI shows two notifications instead of one. Every item added after only shows one notification, as intended. The Exception property is of type `System.Exception`, which for the purpose of testing is just instantiated with `new Exception("Test Text"))`. – Jack Sep 06 '18 at 13:15
  • I am 100% sure. I have `CollectionChanged` events which are only fired once. I have breakpoints at every stage of the notification creation that show me there is only 1 item in the collection. Even once the notifications are shown, showing 2 identical messages, the collection still has only one item. May I stress that this only happens for the first item added to the collection during the session and does not repeat for any item added after. – Jack Sep 06 '18 at 13:17
  • I have added an update to the question. – Jack Sep 06 '18 at 13:58
  • I tried using your xaml and I cannot reproduce your error, Is there any code that you are not showing us that might be of relevance? In my code I have a closed popup, add an alarm, and then show the popup and only have 1 value showing. – Kevin Cook Sep 07 '18 at 18:00

2 Answers2

2

I ran into the same issue recently. I fixed it by doing this in order AllowsTransparency="True" IsOpen="True". For some reason if you specify IsOpen first the transparency doesn't work. Also note IsOpen is set to be always true. That fixed my problem of duplication and the transparency issue. Hope that helps.

<Popup AllowsTransparency="True" IsOpen="True">
    <!--your content goes here-->
</Popup>
ebi
  • 21
  • 1
  • 3
0

The duplication occurs if the Popup is not opened before the first item is added to the collection.

In order to correct the issue there were three steps:

  1. Add a setter and to the ShowAlarmNotifications property so it may be set directly and update the usages:

    private bool _showAlarmNotifications;
    
    
    public bool ShowAlarmNotifications
    {
        get => _showAlarmNotifications;
        set
        {
            _showAlarmNotifications = value;
            OnPropertyChanged();
        }
    }
    
    
    AlarmNotifications.CollectionChanged += (sender, args) =>
    {
        ShowAlarmNotifications = AlarmNotifications.Any();
    };
    
  2. Create a Loaded event for the View and set ShowAlarmNotifications to true:

    private void View_OnLoaded(object sender, RoutedEventArgs e)
    {
        if (DataContext is ViewModel vm)
            vm.ShowAlarmNotifications = true;
    }
    
  3. Create a Loaded event for the Popup and set ShowAlarmNotifications to false:

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

The ItemsControl no longer duplicates the first entry and the Popup is not open when the application starts up.

This is a messy solution and still doesn't explain why the duplication happens but it does satisfy the requirements.

Jack
  • 886
  • 7
  • 27