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

WPF与MVVM:如何通过嵌套UserControl向ViewModel传递对象

解决嵌套UserControl依赖属性传递为null的问题

问题根源

你的SubSubUserControl在OnInitialized中初始化ViewModel时,依赖属性Object的绑定值还未完成赋值。WPF的控件初始化流程里,OnInitialized会先于绑定值的更新执行,所以此时Object还是默认的null。

解决方案

方案1:监听依赖属性变化,动态更新ViewModel

修改SubSubUserControl的依赖属性注册逻辑,添加属性变更回调,当Object值真正传入时再初始化ViewModel:

public static readonly DependencyProperty ObjectProperty = DependencyProperty.Register(
    nameof(Object), 
    typeof(Object), 
    typeof(SubSubUserControl),
    new PropertyMetadata(null, OnObjectPropertyChanged));

public Object Object
{
    get => (Object)GetValue(ObjectProperty);
    set => SetValue(ObjectProperty, value);
}

private static void OnObjectPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var control = (SubSubUserControl)d;
    // 当属性值更新时,初始化ViewModel
    control.DataContext = new SubSubUserControlViewModel(e.NewValue as Object);
}

protected override void OnInitialized(EventArgs e)
{
    InitializeComponent();
    // 不再在此处初始化ViewModel,交给属性变更回调处理
    base.OnInitialized(e);
}

方案2:推迟ViewModel初始化到Loaded事件

Loaded事件会在控件完全加载、绑定值已更新后触发,此时Object属性已获得正确值:

protected override void OnInitialized(EventArgs e)
{
    InitializeComponent();
    Loaded += SubSubUserControl_Loaded;
    base.OnInitialized(e);
}

private void SubSubUserControl_Loaded(object sender, RoutedEventArgs e)
{
    DataContext = new SubSubUserControlViewModel(Object);
    Loaded -= SubSubUserControl_Loaded; // 避免重复触发
}

方案3:基于MVVM的间接传递(更推荐)

既然SubUserControl已经将DataContext设置为SubUserControlViewModel,可以在该ViewModel中暴露Object属性,让SubSubUserControl直接绑定父ViewModel的属性,无需依赖控件的依赖属性:

  1. 修改SubUserControlViewModel,添加Object属性:
public class SubUserControlViewModel
{
    public Object Object { get; }

    public SubUserControlViewModel(Object obj)
    {
        Object = obj;
    }
}
  1. 修改SubUserControl的XAML,让SubSubUserControl绑定父级ViewModel的Object:
<local:SubSubUserControl Object="{Binding Object}" />
  1. SubSubUserControl的后台代码可保持原逻辑,此时绑定的是ViewModel的属性,值会在DataContext设置后正确传递。

额外提示

  • MainWindow中的Object是普通CLR属性,若后续需要动态更新,建议实现INotifyPropertyChanged接口,否则绑定无法响应属性值变化。
  • 依赖属性命名尽量避免和系统类型Object重名,比如改为MyObject,减少代码混淆。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 21:35:16