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

Prism WPF动态加载UserControl并向其ViewModel设置MachineId属性求助

问题根因

你手动添加MachineDashboard时,控件的DataContext是Prism默认注入的独立MachineDashboardViewModel实例,因此Style中绑定的MachineId可以正确找到VM中的对应属性。当控件放到ItemsControl的DataTemplate中时,每个控件的默认DataContext会被替换为Machines集合的元素对象,你写在Style中的绑定找不到正确的VM属性,哪怕写死依赖属性值,也会被双向绑定的失效结果覆盖,导致值无法传递到VM。

推荐解决方案(适配Prism DI规范)

步骤1:在父ViewModel中预创建带MachineId的子VM集合

由于你的MachineDashboardViewModel需要依赖注入,不要直接手动实例化,通过Prism的IContainerProvider创建实例,从数据库读取到设备ID后直接赋值给对应VM:

public class HomeViewModel : BindableBase
{
    private readonly IContainerProvider _containerProvider;
    public ObservableCollection<MachineDashboardViewModel> Machines { get; } = new();

    // 注入容器提供器
    public HomeViewModel(IContainerProvider containerProvider)
    {
        _containerProvider = containerProvider;
        LoadMachinesFromDb();
    }

    private void LoadMachinesFromDb()
    {
        // 替换为实际从数据库读取设备ID的逻辑
        List<int> dbMachineIds = new List<int> { 1, 2, 3 };
        foreach (var machineId in dbMachineIds)
        {
            // 容器自动注入IDialogService、ILogger等依赖
            var machineVm = _containerProvider.Resolve<MachineDashboardViewModel>();
            machineVm.MachineId = machineId;
            Machines.Add(machineVm);
        }
    }
}

步骤2:简化XAML绑定,移除无效依赖属性绑定

你可以直接废弃原来的MachineId_DP依赖属性和对应的Style绑定,ItemsControl直接绑定预创建的VM集合即可:

<ItemsControl Grid.Row="1" ItemsSource="{Binding Machines}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <!-- 直接把DataContext绑定为预创建的VM实例 -->
            <local:MachineDashboard DataContext="{Binding}" Margin="10"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

可选方案:保留依赖属性的兼容实现

如果你需要保留MachineDashboard的MachineId_DP依赖属性做封装,只需要给依赖属性添加属性变更回调,直接给控件自身的VM赋值,规避DataContext变化带来的绑定失效问题:

// MachineDashboard.xaml.cs 后台代码
public static readonly DependencyProperty MachineId_DPProperty = DependencyProperty.Register(
    "MachineId_DP", 
    typeof(int), 
    typeof(MachineDashboard), 
    new PropertyMetadata(default(int), OnMachineIdChanged));

private static void OnMachineIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    if (d is not MachineDashboard control) return;
    if (control.DataContext is MachineDashboardViewModel vm)
    {
        vm.MachineId = (int)e.NewValue;
        control._pendingMachineId = null;
        return;
    }
    // VM未初始化时暂存值,等待DataContext赋值
    control._pendingMachineId = (int)e.NewValue;
}

private int? _pendingMachineId;
public MachineDashboard()
{
    InitializeComponent();
    // 监听DataContext变化,赋值暂存的MachineId
    DataContextChanged += (s, e) =>
    {
        if (e.NewValue is MachineDashboardViewModel vm && _pendingMachineId.HasValue)
        {
            vm.MachineId = _pendingMachineId.Value;
            _pendingMachineId = null;
        }
    };
}

此时你可以直接沿用原来的动态绑定写法,不需要修改ItemsControl的XAML。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 23:39:01