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

WPF ListBox绑定数据源更新不触发(新增项正常)问题求助

WPF ListBox中IsDirty标记不更新的问题

问题场景

系统包含层级对象:Order(对应代码中的OneOff)→ Store → Planogram,均继承自实现INotifyPropertyChanged的基类,通过MVVM Toolkit实现属性变更通知,所有属性变更会自动设置IsDirty=true。子集合的CollectionChanged事件已绑定,用于向上传递变更。

ViewModel维护ObservableCollection<OneOff>,ListBox绑定该集合,ItemTemplate内的TextBlock通过转换器绑定IsDirty属性来显示*标记。

异常现象

  • 修改从数据库加载的Order的任意子属性时,IsDirty已被正确设置为true,但ListBox中对应的*始终不显示。
  • 新增空白Order并添加到集合后,*能正常显示。

相关代码片段

包含IsDirty的基类

public class BaseOneOffStorePlanogram : ObservableObject, IOneOffData
{
    private bool _isDirty = false;

    public bool IsDirty 
    { 
        get { return _isDirty; } 
        set { 
            if(value != _isDirty)
            {
                _isDirty = value;
                base.OnPropertyChanged("IsDirty");
            }
        } 
    } 
    public string LastModifiedBy { get; set; }
    public DateTime? LastModifiedOn { get; set; }

    protected override void OnPropertyChanged(PropertyChangedEventArgs e)
    {
        if (e.PropertyName != "IsDirty")
        {
            base.OnPropertyChanged(e);
            IsDirty = true;
        }
     }
}

Store对象代码片段

public string StoreNumber
{
    get { return _StoreNumber; }
    set
    {
        _StoreNumber = value;
        base.OnPropertyChanged("StoreNumber");
    }
}
public DateTime? PricingDateOverride
{
    get
    {
        return _PricingDateOverride;
    }
    set
    {
        _PricingDateOverride = value;
        base.OnPropertyChanged("PricingDateOverride");
    }
}

public OneOffStore()
{
    _OneOffStorePlanograms = new ObservableCollection<OneOffStorePlanogram>();
    _OneOffStorePlanograms.CollectionChanged += _OneOffStorePlanograms_CollectionChanged;
}

private void _OneOffStorePlanograms_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if(e.OldItems != null)
    {
        foreach( OneOffStorePlanogram oosp in e.OldItems)
        {
          oosp.PropertyChanged += InvokeCollectionChanged;
        }
    }
    if( e.NewItems != null)
    {
        foreach(OneOffStorePlanogram oosp in e.NewItems)
        {
            oosp.PropertyChanged += InvokeCollectionChanged;
        }
    }
}

private void InvokeCollectionChanged(object sender, PropertyChangedEventArgs e)
{
    OnPropertyChanged("OneOffStorePlanograms");
}

ViewModel集合定义部分

public ObservableCollection<OneOff> OneOffs
{
    get { return _oneOffs; }
}

private void InitializeForm(){
    _oneOffs = new ObservableCollection<OneOff>();

    _selectedStores = new ObservableCollection<Store>();
    _selectedPlanograms = new ObservableCollection<Models.Planogram>();
    _useEffectiveDate = false;
   
    LoadPlanograms();
    LoadStores();
    LoadOneOffs();
    //GetUnprocessedOneOffs();
   
    _oneOffs.CollectionChanged += OneOffs_CollectionChanged;
}

XAML代码片段

<ListBox x:Name="lstActiveJobs" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" 
         ItemsSource="{Binding OneOffs, NotifyOnSourceUpdated=True,UpdateSourceTrigger=PropertyChanged}" 
         SelectedItem="{Binding SelectedOneOff}" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="10"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="*"/>
                </Grid.RowDefinitions>
                <TextBlock Text="{Binding OneOffName, PresentationTraceSources.TraceLevel=High}" Grid.Row="0" Grid.Column="0" />
                <TextBlock Text="*" x:Name="HasChangeModifier" Grid.Row="0" Grid.Column="1"  
                           Visibility="{Binding IsDirty, Converter={StaticResource BoolToVis}, UpdateSourceTrigger=PropertyChanged}"/>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

问题分析与解决方案

核心问题

从数据库加载的对象,其层级变更没有传递到最上层的OneOff对象的IsDirty属性变更通知,或者OneOff对象的IsDirty变更未触发UI更新。

具体排查点与修复方案

  1. 补全层级变更传递链
    当前Store对象的子集合变更仅触发了OneOffStorePlanograms的属性通知,未传递到父级OneOff对象。需在OneOff对象中为其包含的Store集合绑定CollectionChanged事件,同时为每个Store对象绑定PropertyChanged事件,当Store的属性或子集合变更时,设置OneOff的IsDirty=true。

  2. 检查基类事件逻辑
    基类中重写OnPropertyChanged时,先调用base.OnPropertyChanged(e)再设置IsDirty=true,需确保子对象的变更能向上传递到OneOff,触发其IsDirty的变更通知。确认OneOff类正确继承自BaseOneOffStorePlanogram。

  3. 修复数据库加载对象的事件绑定缺失
    新增空白Order时会自动绑定子集合事件,但从数据库加载的对象,未为已存在的子对象(Store、Planogram)绑定PropertyChanged事件。在LoadOneOffs方法中,遍历每个加载的OneOff及其下的Store,为Store的PropertyChanged事件绑定处理程序,同时为Store的Planogram集合中已存在的每个Planogram绑定PropertyChanged事件。

  4. 验证UI绑定正确性
    确认BoolToVis转换器逻辑正确:当IsDirty=true时返回Visibility.Visible,否则返回Collapsed或Hidden。可在OneOff的IsDirty setter中添加调试输出,确认修改子属性时确实触发了IsDirty变更和OnPropertyChanged("IsDirty")调用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:19:57