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

WPF中UserControl与Window的ViewModel重复实例化问题求助

问题根源与解决方案

你遇到的问题很明确:你在Window和UserControl的Resources中分别实例化了同一个ScanVM类,这就导致了两个完全独立的ViewModel实例——Window里的ABC是一个,UserControl里的ABC是另一个,自然无法实现命令和数据的互通。

解决思路:只创建一次ViewModel实例,让Window和UserControl共享它

最简单的修复方式是把ViewModel的实例定义在Window的Resources中(或者更高层级的资源,比如App.xaml),然后让UserControl直接使用这个已有的实例,而不是自己再创建新的。

步骤1:修改UserControl的XAML,移除自己的ViewModel资源

打开你的ScanView.xaml,删除<UserControl.Resources>里的<t:ScanVM x:Key="ABC"/>,同时调整DataContext的绑定,让它继承父级(Window中的Grid)的DataContext:

<UserControl x:Class="ScanVM.ScanView" 
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:t="clr-namespace:ScanVM" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="501.305">
    <!-- 移除UserControl内部的ScanVM资源定义 -->
    <DockPanel>
        <!-- 这里的DataContext会自动继承自父级(Window中的Grid)的DataContext,也就是Window里的ABC实例 -->
        <Grid ShowGridLines="True" Margin="10">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="1*" />
                <ColumnDefinition Width="5*" />
                <ColumnDefinition Width="1*" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="1*" />
                <RowDefinition Height="10*" />
                <RowDefinition Height="1*" />
            </Grid.RowDefinitions>
            <Label Content="Geräte:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Right" Margin="0,10,10,0"/>
            <DataGrid ItemsSource="{Binding Path=ScanIDs, Mode=OneWay}" Grid.Column="1" HorizontalAlignment="Left" Margin="10,10,0,0" Grid.Row="1" VerticalAlignment="Top" AutoGenerateColumns="false" Height="152" >
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding ScanIds}" ClipboardContentBinding="{x:Null}" Header="Bezeichnung" MinWidth="200"/>
                </DataGrid.Columns>
            </DataGrid>
        </Grid>
    </DockPanel>
</UserControl>

步骤2:保留Window的ViewModel资源与绑定

你的Window代码不需要大改,因为你已经把ScanView的DataContext绑定到了Window的ABC实例:

<t:ScanView DataContext="{Binding Source={StaticResource ABC}}"/>

这会让UserControl完全使用Window中创建的那个ScanVM实例,命令和数据就会统一了。

额外的优化建议

如果你希望ViewModel的实例在整个应用中都唯一,还可以把它定义在App.xaml的Resources里,这样所有页面和控件都能引用同一个实例。

另外,对于更复杂的项目,推荐使用依赖注入(比如Prism、Microsoft.Extensions.DependencyInjection)来管理ViewModel的生命周期,确保实例的唯一性和可测试性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 03:42:01