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

WinUI3/.NET9中更新ItemsSource后背景色绑定值异常

问题:ObservableCollection更新后自定义控件背景色绑定异常,其他属性正常

我通过数据模板绑定ObservableCollection中的值更新自定义控件背景色,但集合更新后背景色绑定获取错误值,其他属性更新正常。已尝试修改属性名称、属性变更时重新应用模板,均无效。

相关代码片段

CustomControls项目/Themes/Generic.xaml

<Style TargetType="local:CustomTableCard">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:CustomTableCard">
                <Grid Height="300" Width="300" BorderThickness="4" Background="{Binding BackgroundColorProp, RelativeSource={RelativeSource TemplatedParent},
                                Mode=OneWay, FallbackValue='Black', TargetNullValue='Blue'}">

CustomControls项目/CustomTableCard.cs

public class CustomTableCard : Control
{
   public static readonly DependencyProperty BackgroundColorProperty = 
   DependencyProperty.Register(
      nameof(BackgroundColorProperty),
      typeof(string),
      typeof(CustomTableCard),
      new PropertyMetadata(null));

   public string BackgroundColorProp
   {
      get => (string)GetValue(BackgroundColorProperty);
      set => SetValue(BackgroundColorProperty, value);
   }

   public CustomTableCard()
   {
      this.DefaultStyleKey = typeof(CustomTableCard);
   }

   protected override void OnApplyTemplate()
   {
      base.OnApplyTemplate();
      [...]
   }
}

View项目/CustomTablePage.xaml

<Page.Resources>
    <DataTemplate x:Key="CustomTableItemTemplateNew" x:DataType="Data:CustomTableCardData">
        <ItemContainer>
            <customControls:CustomTableCard TableName="{x:Bind TableNameData, Mode=OneWay}"
                                            TextColor="{x:Bind TextColorData, Mode=OneWay}"
                                            [...]
                                            BackgroundColorProp="{x:Bind BackgroundColorData}"
                                            TableDeletionRequested="CustomTableItem_TableDeletionRequested"
                                            />
        </ItemContainer>
    </DataTemplate>
</Page.Resources>

[...]

<ItemsView x:Name="itemsViewTables" HorizontalAlignment="Stretch"
            ItemTemplate="{StaticResource CustomTableItemTemplateNew}"
            ItemsSource="{x:Bind Data:CustomTableCardDataRepository.customTableItemsCollection, Mode=OneWay}"

View项目/CustomTablePage.xaml.cs

public void loadTables()
{
    CustomTableCardDataRepository.FillCustomTablesCollection((int)userId);

    itemsViewTables.ItemsSource = CustomTableCardDataRepository.customTableItemsCollection;
}

异常现象

  • 页面初始调用loadTables()加载数据时显示正常,背景色符合预期。
  • 未刷新页面,仅再次调用loadTables()填充customTableItemsCollection(数据本身正确)后,新增表格背景色显示异常,颜色在控件间混乱。
  • 切换页面再返回后,所有控件显示恢复正常。
  • 偶尔所有按钮会显示错误的统一背景色,但调试时CustomTableCard的属性值已正确设置为目标颜色,ItemsSource中的数据也完全正确。
  • 重启应用并移除其他卡片后,单个按钮仍会出现背景色异常。

重要新信息

修改按钮默认颜色后,异常显示的颜色也同步改变;调试构造函数时,代码正确设置了目标颜色,并未执行设置为错误颜色的逻辑。推测控件可能复用了已移除控件的旧数据,绑定存在问题。


解决方案

1. 修正依赖属性注册错误

你的BackgroundColorProperty注册存在关键错误:注册名称参数用了nameof(BackgroundColorProperty),但实际对应的CLR属性是BackgroundColorProp,这会导致WPF/UWP依赖属性系统无法正确关联属性,绑定更新时无法通知UI刷新。

修正后的代码:

public static readonly DependencyProperty BackgroundColorPropProperty = 
DependencyProperty.Register(
   nameof(BackgroundColorProp), // 匹配CLR属性名
   typeof(string),
   typeof(CustomTableCard),
   new PropertyMetadata(null, OnBackgroundColorPropChanged)); // 添加属性变更回调确保UI更新

public string BackgroundColorProp
{
   get => (string)GetValue(BackgroundColorPropProperty);
   set => SetValue(BackgroundColorPropProperty, value);
}

// 可选:属性变更回调,强制刷新模板绑定
private static void OnBackgroundColorPropChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
   var control = d as CustomTableCard;
   control?.InvalidateVisual();
}

2. 确保数据模型实现INotifyPropertyChanged

检查CustomTableCardData类是否实现INotifyPropertyChanged接口,当BackgroundColorData变更时触发PropertyChanged事件,否则x:Bind无法感知数据更新。

示例实现:

public class CustomTableCardData : INotifyPropertyChanged
{
    private string _backgroundColorData;
    public string BackgroundColorData
    {
        get => _backgroundColorData;
        set
        {
            if (_backgroundColorData != value)
            {
                _backgroundColorData = value;
                OnPropertyChanged(nameof(BackgroundColorData));
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    // 其他属性同理实现
}

3. 避免重复设置ItemsSource

ObservableCollection本身支持集合变更通知,无需每次调用loadTables()都重新赋值ItemsSource,直接更新集合内容即可:

public void loadTables()
{
    var newItems = CustomTableCardDataRepository.FillCustomTablesCollection((int)userId);
    // 清空现有集合并添加新项,保留原集合引用
    CustomTableCardDataRepository.customTableItemsCollection.Clear();
    foreach (var item in newItems)
    {
        CustomTableCardDataRepository.customTableItemsCollection.Add(item);
    }
    // 移除重复赋值:itemsViewTables.ItemsSource = ...;
}

4. 清理控件复用状态

ItemsControl会复用控件容器,若控件未清理旧状态会导致值残留,可在CustomTableCard的Unloaded事件中清理背景色:

protected override void OnUnloaded(RoutedEventArgs e)
{
    base.OnUnloaded(e);
    // 清理背景色,避免复用旧值
    BackgroundColorProp = null;
}

内容的提问来源于stack exchange,提问作者Arthur Buzas Baccan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 05:54:53