当前位置: 首页 > news >正文

记录一次附加属性失效全过程

1、我为了实现View到ViewModel的自动绑定,写了附加属性

local:ViewModelSelector.AutoWireViewModel="True"

没想到它不触发,我将dll的触发属性迁移到本地项目,触发了,但是报错MainViewModel找不到Text
2、我的xaml构造如下
MainView:

<Grid><Grid.ColumnDefinitions><ColumnDefinition /><ColumnDefinition /></Grid.ColumnDefinitions><Button Width="200" Content="{Binding Name}" /><ContentControl Grid.Column="1" Content="{Binding View}" />
</Grid>

HomeView:

 td:ViewModelSelector.AutoWireViewModel="True"
<StackPanel><TextBlock Text="{Binding Text}" />
</StackPanel>

此时发现附加属性触发,但是viewModelType为null,
打断点尝试,发现ViewModel没有注册,
注册完成后运行,失败,原来在同一目录去查找了
继续修改,将View和ViewModel替换

var name = view.GetType().FullName.Replace("View", "ViewModel");
var viewModelType = Type.GetType(name);
if (viewModelType != null)
{var viewModel = TangdaoApplication.Provider.GetService(viewModelType);view.DataContext = viewModel;
}

继续运行,
界面已经能出现 “World” → HomeView.DataContext 确实是 HomeViewModel,绑定完全正确。
但 VS 依旧报 “MainViewModel 上找不到 Text” → 说明有一处绑定表达式并没有指向 HomeViewModel,而是指到了 MainViewModel;运行期只是碰巧在 HomeView 区域看见了正确的值
此时我使用PresentationTraceSources.TraceLevel=High炸出所有报错
我怀疑附加属性运行了两次
我使用

 view.ClearValue(FrameworkElement.DataContextProperty); 

切断继承链并延迟到Initialized去触发,成功了
成功,此时打包代码到dll,继续使用dll执行。
把完全相同的代码从 EXE 项目搬到 DLL 后,又出现 “MainViewModel 找不到 Text”
没触发???为此,我对dll的附加属性类所有行打上断点
继续运行
还是没触发???
我添加代码

 public HomeView(){InitializeComponent();bool flag = IT.Tangdao.Framework.Selectors.ViewModelSelector.GetAutoWireViewModel(this);System.Diagnostics.Debug.WriteLine($"[HomeView] AutoWireViewModel={flag}");}

是true,但是为什么不进断点
为什么附加属性不触发,我使用System.Diagnostics.Debugger.Break();强制进断点
可以进去,现在我怀疑是JIT问题

 // 1. 显式静态构造static ViewModelSelector(){// 2. 强制触摸字段,防止 JIT 死代码消除var dummy = AutoWireViewModelProperty;}

还是不起作用出现 “MainViewModel 找不到 Text”
上火了,我将能打断点的可疑地方全部上断点
直到

  private HomeView _view;public HomeView View{get => _view;set => SetProperty(ref _view, value);}

get方法卡死,导致VS2022卡出去,吆喝,来活了
我现在怀疑HomeView 实例并不是由 XAML 解析器创建的,

 View = TangdaoApplication.Provider.GetService<HomeView>();

我检查我的IOC容器,测压多次应该没问题,那么我对IOC容器解析没问题
但是以防万一,我将解析改为new,new HomeView()
还是卡死,此时
我改为从ViewModel先行

 private HomeViewModel _view;public HomeViewModel View{get => _view;set => SetProperty(ref _view, value);}View = TangdaoApplication.Provider.GetService<HomeViewModel>();

加上数据模板

  <DataTemplate DataType="{x:Type vm:HomeViewModel}"><view:HomeView /></DataTemplate>

此时不报错,界面成功出现数据

这是因为
代码 new 视图 + SetProperty 触发属性通知 → 设计器反复创建 → 递归死循环
这是 View-First 最典型的“设计时炸弹”,无论 new HomeView() 还是 IOC 解析 HomeView,只要视图由代码实例化并塞进属性通知链路,都会中招;
ViewModel-First 天然免疫,因为 XAML 解析器只在需要呈现时才创建视图,永远不会递归触发属性通知。

阶段 环境 现象 关键发现
初期调试 EXE 项目 附加属性不触发 代码在本地可调试
中期迁移 DLL 迁移 附加属性完全失效 静态构造函数可能被优化
架构调整 View-First 设计时递归卡死 new HomeView() 导致属性通知循环
最终方案 ViewModel-First 运行正常 数据模板 + IOC 容器解析
维度 View-First 模式 ViewModel-First 模式
实例化时机 代码中显式 new 或 IOC 解析 XAML 解析器按需创建
设计时支持 容易递归卡死 VS 天然免疫设计时问题
数据绑定 容易受继承污染 数据模板明确关联
内存管理 可能重复创建视图 按需创建,生命周期清晰
调试难度 高(属性通知循环) 低(清晰的创建链路)

最后总结一句话
“在 WPF 里,视图 new 得越少,世界越干净;
把 new 交给 XAML,把逻辑交给 VM,把断点留给自己。”

http://www.sczhlp.com/news/131000/

相关文章:

  • 青岛网站建设商家网站未做安全隐患检测怎么拿shell
  • 怎样进行网站建设步骤个人网站 论坛
  • 济南网站万词优化吉林省建设工程造价信息网
  • html5微网站demo买卖链接网
  • 最好建网站系统的软件wordpress选择幻灯片模版没有用
  • 关于网站开发所需的知识网页设计素材以及效果图
  • 大气绿色网站模板网络教育全程托管
  • wordpress支持建多个站点吗山西免费网站制作
  • 自己做物流网站十堰网络推广平台
  • 扬中信息网公司网站如何seo
  • 网站后台 不能删除文章wordpress 背景图
  • iis配置网站访问权限贵州企业网站
  • 山东德州网站建设修改wordpress菜单
  • 找人做网站需要准备什么材料wordpress设计网页
  • 企业官方网站制作推广软件织梦网站会员功能
  • 广东建设局网站首页wordpress长文分页
  • 崇明网站建设上海设计公司排名前十强20
  • 网站域名空间地址seo价格是多少
  • 做英语四级题的网站网站建设是系统工程
  • 台州seo网站推广费用来广营网站建设
  • 如何做带后台的网站纯前端网站怎么做rest
  • 如东网站建设wordpress开发一个app后台
  • vs2010网站开发 SQLwordpress小程序推荐
  • 建设小网站教程泰安小程序网络公司
  • 品牌网站制作方案免费国产linux服务器系统
  • 做网站一个月20万政务公开与网站建设工作总结存在问题和困难
  • 网站权重6了该则么做优化方案网站 制作登录
  • 网站开发前期方案一个网站怎么做聚合
  • 一般做自己的网站需要什么临漳企业做网站推广
  • 网站seo啥意思怎么做个人网页制作教程dw