1

I have a very weird problem. I am binding ListBox.ItemSource to an ObservableCollection. I subscribe to the CollectionChanged event of the collection if any items are added, I show the window with the ListBox that is bound to the collection. The first time I do this, the ListBox shows only one item as it should. The second time however, the ListBox which is in a newly created Window shows two items. I have verified that the ObservableCollection never has more than one item in it. What the heck is going on?

Here is the code in my view model.

    public ObservableCollection<AlarmItemViewModel> RaisedAlarms
    {
        get { return _raisedAlarms; }
        set { _raisedAlarms = value; RaisePropertyChanged("RaisedAlarms"); }
    }

    protected override void OnAlarmRaised(AlarmItem a_alarmItem)
    {
        var activeAlarmItems = from alarmItem in RaisedAlarms
                               select alarmItem.AlarmItem;

        if (!activeAlarmItems.Contains(a_alarmItem))
            RaisedAlarms.Add(new AlarmItemViewModel(this, a_alarmItem));
    }

    private void OnActiveAlarmsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        if (e.Action == NotifyCollectionChangedAction.Add)
        {
            if (_alarmRaiseWindow == null)
            {
                _alarmRaiseWindow = new SetupWindow();
                _alarmRaiseWindow.Title = "Alarm Raised";
                _alarmRaiseWindow.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
                _alarmRaiseWindow.Topmost = true;
                _alarmRaiseWindow.Content = new AlarmRaise();
                _alarmRaiseWindow.DataContext = this;
                _alarmRaiseWindow.Closed += OnAlarmNotifyClosed;
            }
        }

        if (!RaisedAlarms.Any() && _alarmRaiseWindow != null)
        {
            _alarmRaiseWindow.Close();
        }
    }

    private void OnAlarmNotifyClosed(object sender, EventArgs e)
    {
        if (_alarmRaiseWindow != null)
        {
            _alarmRaiseWindow.Closed -= OnAlarmNotifyClosed
            _alarmRaiseWindow = null;
        }
    }

Here is a simplified version of the XAML:

<UserControl x:Class="MyNamespace.AlarmRaise"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300" Width="400" Height="300">
    <Border>
        <Grid>
            <ListBox ItemsSource="{Binding RaisedAlarms, Mode=OneWay}">
            </ListBox>
        </Grid>
    </Border>
</UserControl>

Edits:

The way my code works is basically this. When the first item in the collection is added it shows a Window containing a ListBox bound the collection, so if any others are added in the collection they will show as well. Once the last item in the collection is removed, the Window is closed.

So say I have an "Alarm 1", "Alarm 2" and "Alarm 3", and they show the first time, and I remove them by sleeping them for five seconds, then the next time the window comes up, it will show the first item twice: "Alarm 1", "Alarm 1", "Alarm 2", "Alarm 3". Not always in that order.

This is true for subsequent iterations as well (i.e. it never shows up more than doubled).

Further Edits:

It seems that the issue is either with the view or the binding. The view model is always showing the correct data at the correct times. I am wondering if maybe I need to refresh the binding in some way, or bind in code. I am wanting to avoid both.

4

1 回答 1

0

呜呼,我已经解决了这个问题!它与设置DataContext和调用的顺序有关Show()。如果我设置DataContext after I call ,它工作正常Window.Show()Show()糟糕,我在示例代码中省略了对的调用。我不得不更改代码以删除与此问题无关的外部依赖项,并且会提出更多问题。我现在会编辑它。

于 2012-07-17T16:35:50.900 回答