You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WPF ListBox绑定ObservableCollection后更新异常求助

WPF ListBox绑定ObservableCollection同步异常问题

原本在多视图中使用ListBox绑定ObservableCollection,增删操作和视图同步均正常。但为列表项添加图标(根据item的monitoring属性显示/隐藏),添加ListBox.ItemTemplate后,出现ListBox无法持续同步集合的问题:添加项有时显示有时不显示,多视图不同步,甚至出现空白项。图标显示逻辑正常,但列表更新异常。

修改前XAML

<ListBox
    Name="CameraTargetsListbox"
    Style="{DynamicResource NeuronListBoxStyle}" 
    VerticalAlignment="Stretch"
    HorizontalAlignment="Stretch"
    HorizontalContentAlignment="Stretch"
    VerticalContentAlignment="Stretch"
    Margin="0,8,0,4"
    Height="140"
    ItemContainerStyle="{DynamicResource NeuronListBoxItem_CameraTargets}"/>

修改后XAML

<ListBox
    Name="CameraTargetsListbox"
    Style="{DynamicResource NeuronListBoxStyle}" 
    VerticalAlignment="Stretch"
    HorizontalAlignment="Stretch"
    HorizontalContentAlignment="Stretch"
    VerticalContentAlignment="Stretch"
    Margin="0,8,0,4"
    Height="140"
    ItemContainerStyle="{DynamicResource NeuronListBoxItem_CameraTargets}">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <ContentPresenter 
                            Content="{Binding MonitoringItemIcon,  UpdateSourceTrigger=PropertyChanged}"  
                            Margin="-4,0,10,0" />
                <TextBlock Text="{Binding DisplayName, UpdateSourceTrigger=PropertyChanged}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

后台绑定代码(未修改)

public CameraTargetsControl()
{            
    InitializeComponent();
    this.DataContext = this;
    
    CameraTargetsListbox.ItemsSource = PropertyList;
    // ...其他代码
}

列表更新逻辑

每次收到新列表时,与ObservableCollection(PropertyList)对比,处理增删改:

_ = Dispatcher.BeginInvoke(() => 
{
    List<int> addList = new();
    List<int> deleteList = new();
    List<(int, int)> updateList = new(); // index from incoming list, index from listbox

    CameraTarget selectedTarget = null;

    CameraTargetsListbox.SelectionChanged -= CameraTargetsListbox_SelectionChanged;

    if (CameraTargetsListbox.SelectedIndex != -1) selectedTarget = (CameraTarget)CameraTargetsListbox.SelectedItem;
    
    // Check for additions and deletions
    foreach (var target in targetList)
    {
        bool found = false;
        foreach (var listedTarget in PropertyList)
        {
            if (target.Class == CameraTarget.TargetClass.AIS)
            {
                if (listedTarget.MMSI == target.MMSI)
                {
                    updateList.Add((targetList.IndexOf(target), PropertyList.IndexOf(listedTarget)));
                    found = true;
                    break;
                }
            }
            else if (listedTarget.TargetIndex == target.TargetIndex)
            {
                updateList.Add((targetList.IndexOf(target), PropertyList.IndexOf(listedTarget)));
                found = true;
                break;
            }
        }
        if (!found) { addList.Add(targetList.IndexOf(target)); }                    
    }

    // Check for deletions
    foreach (var listedTarget in PropertyList)
    {
        bool found = false;
        foreach (var target in targetList)
        {
            if (target.Class == CameraTarget.TargetClass.AIS)
            {
                if (listedTarget.MMSI == target.MMSI)
                {
                    found = true;
                    break;
                }
            }
            else if (listedTarget.TargetIndex == target.TargetIndex)
            {
                found = true;
                break;
            }
        }
        if (!found) deleteList.Add(PropertyList.IndexOf(listedTarget));
    }

    if (updateList.Count > 0)
    {
        foreach (var index in updateList)
        {
            if (index.Item2 == CameraTargetsListbox.SelectedIndex)
            {
                if (PropertyList[index.Item2].Monitoring && PropertyList[index.Item2].MonitoringItemIcon == null)
                {
                    PropertyList.RemoveAt(index.Item2);
                    PropertyList.Insert(index.Item2, targetList[index.Item1]);
                }
                else PropertyList[index.Item2] = targetList[index.Item1];
                CameraTargetsListbox.SelectedIndex = index.Item2;
                RefreshSelectedInfo();
            }
            else if(PropertyList[index.Item2].Monitoring && PropertyList[index.Item2].MonitoringItemIcon == null)
            {
                PropertyList.RemoveAt(index.Item2);
                PropertyList.Insert(index.Item2, targetList[index.Item1]);
            }
            // Capture name updates
            else if (PropertyList[index.Item2].ToString() != targetList[index.Item1].ToString())
            {
                PropertyList.RemoveAt(index.Item2);
                PropertyList.Insert(index.Item2, targetList[index.Item1]);
            }
            else PropertyList[index.Item2] = targetList[index.Item1];

        }
    }
    if (deleteList.Count > 0)
    {
        foreach (int index in deleteList)
        {
            if (index == CameraTargetsListbox.SelectedIndex) DeleteSelectedTarget(null, null);
            else PropertyList.RemoveAt(index); 
        }
    }
    if (addList.Count > 0)
    {
        foreach (int index in addList)
        {
            PropertyList.Add(targetList[index]);
        }
    }
    
    CameraTargetsListbox.SelectionChanged += CameraTargetsListbox_SelectionChanged;
    CheckPropertyList();
});

尝试过添加UpdateSourceTrigger=PropertyChanged但无效,ObservableCollection应该自动处理通知,不理解为何修改模板后出现同步问题,寻求解决方法。


内容的提问来源于stack exchange,提问作者ZadiusC

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 09:44:54