DataGrid模板中自定义CLightSystem控件Value属性为空问题排查
原因分析
- 绑定时机不匹配:
OnApplyTemplate执行时,DataGrid单元格的数据绑定可能还未完成,此时Value属性为空,调用UpdateLight()不会触发任何灯光状态变更。单独使用控件时,绑定完成早于模板应用,所以能正常工作,但DataGrid内的虚拟化加载逻辑会改变这个顺序。 - 未监听属性变化:自定义控件仅在模板应用时执行一次
UpdateLight(),当Value通过绑定获得有效值后,没有自动触发状态更新的逻辑。 - 绑定路径可能存在问题:需确认
CncCollectionM12中的数据项确实包含公共、名称完全匹配的StatusDrawing属性(WPF绑定大小写敏感),且属性值变化时能通知UI(实现INotifyPropertyChanged)。
解决方案
1. 为Value属性添加变更回调
修改依赖属性注册代码,添加PropertyChangedCallback,确保Value值变化时自动更新灯光状态:
public static readonly DependencyProperty ValueProperty = DependencyProperty.Register( "Value", typeof(string), typeof(CLightSystem), new PropertyMetadata(default(string), OnValueChanged)); private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = d as CLightSystem; control?.UpdateLight(); }
2. 增强UpdateLight()的鲁棒性
添加空值和控件实例判断,避免空引用异常,同时处理未匹配到的Value情况,修正原代码中橙色灯光阴影颜色的错误:
public void UpdateLight() { // 若控件实例未初始化或Value为空,重置为默认灰色 if (redLight == null || orangeLight == null || greenLight == null || string.IsNullOrEmpty(Value)) { redLight?.Fill = new SolidColorBrush(Colors.LightGray); orangeLight?.Fill = new SolidColorBrush(Colors.LightGray); greenLight?.Fill = new SolidColorBrush(Colors.LightGray); return; } switch (Value) { case "GESPERRT": redLight.Fill = new SolidColorBrush(Colors.Red); redLight.Effect = new DropShadowEffect() { Color = new Color { A = 255, R = 255, G = 0, B = 0 }, BlurRadius = 3, Direction = -90, ShadowDepth = 0 }; // 重置其他灯光 orangeLight.Fill = new SolidColorBrush(Colors.LightGray); orangeLight.Effect = null; greenLight.Fill = new SolidColorBrush(Colors.LightGray); greenLight.Effect = null; break; case "IN BEARBEITUNG": orangeLight.Fill = new SolidColorBrush(Colors.DarkOrange); orangeLight.Effect = new DropShadowEffect() { Color = new Color { A = 255, R = 255, G = 165, B = 0 }, BlurRadius = 3, Direction = -90, ShadowDepth = 0 }; // 重置其他灯光 redLight.Fill = new SolidColorBrush(Colors.LightGray); redLight.Effect = null; greenLight.Fill = new SolidColorBrush(Colors.LightGray); greenLight.Effect = null; break; case "FREIGEGEBEN": greenLight.Fill = new SolidColorBrush(Colors.Green); greenLight.Effect = new DropShadowEffect() { Color = new Color { A = 255, R = 0, G = 255, B = 0 }, BlurRadius = 3, Direction = -90, ShadowDepth = 0 }; // 重置其他灯光 redLight.Fill = new SolidColorBrush(Colors.LightGray); redLight.Effect = null; orangeLight.Fill = new SolidColorBrush(Colors.LightGray); orangeLight.Effect = null; break; default: // 默认情况重置所有灯光 redLight.Fill = new SolidColorBrush(Colors.LightGray); redLight.Effect = null; orangeLight.Fill = new SolidColorBrush(Colors.LightGray); orangeLight.Effect = null; greenLight.Fill = new SolidColorBrush(Colors.LightGray); greenLight.Effect = null; break; } }
3. 验证数据绑定的正确性
- 确保
CncCollectionM12中的数据项拥有公共无参数的StatusDrawing属性,名称拼写完全一致(包括大小写)。 - 如果
StatusDrawing值会动态变化,数据项需实现INotifyPropertyChanged接口:
public class CncDataItem : INotifyPropertyChanged { private string _statusDrawing; public string StatusDrawing { get => _statusDrawing; set { if (_statusDrawing != value) { _statusDrawing = value; OnPropertyChanged(nameof(StatusDrawing)); } } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
4. 可选:临时关闭DataGrid虚拟化(用于验证)
如果怀疑是虚拟化导致的绑定延迟,可以临时关闭虚拟化测试(长期使用会影响大数据量时的性能):
<DataGrid ... VirtualizingStackPanel.IsVirtualizing="False">
内容的提问来源于stack exchange,提问作者Leeeeeeevin
相关产品推荐
相关产品推荐

