当我们在开发自定义的组件的时候,有没有遇到过这种场景,我们明明没有给FrameworkElement.DataContext属性赋null值,为什么他变成null了?

出现这种问题,可能有以下几种场景:

  1. 调试的对象不是同一个对象
  2. 异步代码出现不按常规顺序赋值
  3. 数据绑定,更改了其数值
  4. 数据模版或者样式应用,导致数据被重置

前面几种很好理解,调试的过程中也比较容易发现。这次就简单的来说下第四种场景。

先来看个堆栈:

从堆栈信息里面,我们可以发现,MeasureCore里面调用了ApplyTemplate的代码。

这个是ContentPresenter的部分源代码:

        private void EnsureTemplate()
        {
            DataTemplate oldTemplate = Template;
            DataTemplate newTemplate = null;

            for (_templateIsCurrent = false; !_templateIsCurrent; )
            {                
                _templateIsCurrent = true;
                newTemplate = ChooseTemplate();
                
                if (oldTemplate != newTemplate)
                {
                    Template = null;
                }

                if (newTemplate != UIElementContentTemplate)
                {                    
                    this.DataContext = Content;
                }
                else
                {
                    this.ClearValue(DataContextProperty);
                }
            }

            Template = newTemplate;
            if (oldTemplate == newTemplate)
            {
                StyleHelper.DoTemplateInvalidations(this, oldTemplate);
            }
        }

在首次应用模版的时候,DataContext会被重新赋值。所以就会出现不符合预期的现象。

解决这个问题的办法也很简单,就是在FrameworkElement.ApplyTemplate后,再给DataContext赋值就可以了。

承哥技术交流小作坊


本文会经常更新,请阅读原文: https://huchengv5.gitee.io//post/WPF-DataContext%E8%8E%AB%E5%90%8D%E8%A2%AB%E9%87%8D%E7%BD%AE%E4%B8%BAnull.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

知识共享许可协议 本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名胡承(包含链接: https://huchengv5.gitee.io/ ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系