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

WPF与Prism问题:多UserControl中RadioButton选中状态丢失

问题原因与解决方案

这个问题我之前也碰到过,核心原因是多个TestControl实例共享了同一个TestViewModel实例,导致所有窗口的单选按钮绑定的是同一个SelectedMode属性——当新窗口的单选按钮触发ConvertBack更新属性值时,之前打开的窗口会同步更新选中状态,自然就取消了之前的选中效果。

为什么会共用ViewModel?看你的TestControl XAML代码,你直接在<UserControl.DataContext>里硬编码创建了<vm:TestViewModel/>,如果这个控件被Prism的PopupWindowAction复用,或者你的ViewModel被注册成了单例,就会导致所有TestControl用同一个ViewModel实例。另外,如果你的EnumToBooleanConverter内部维护了静态状态,也可能引发这个问题,但最常见的还是ViewModel实例共享的问题。

解决办法

1. 给每个弹出窗口分配独立的ViewModel(推荐)

不要在TestControl的XAML里直接设置DataContext,而是在弹出窗口时动态创建新的ViewModel实例:

步骤1:修改TestControl XAML

删掉硬编码的DataContext声明:

<!-- 移除这部分代码 -->
<UserControl.DataContext>
    <vm:TestViewModel/>
</UserControl.DataContext>

步骤2:修改MainViewModel的触发逻辑

在弹出窗口前,创建新的TestViewModel实例,并把它作为Confirmation的Content传递:

private void OnClicked(object obj)
{
    int index = Convert.ToInt32(obj);
    // 每次弹出都创建新的ViewModel实例
    var testVm = new TestViewModel();
    var confirmation = new Confirmation()
    {
        Content = testVm,
        Title = $"Bla {index}"
    };

    switch (index)
    {
        case 1: StretchModeRequest1.Raise(confirmation); break;
        case 2: StretchModeRequest2.Raise(confirmation); break;
        case 3: StretchModeRequest3.Raise(confirmation); break;
    }
}

步骤3:绑定TestControl的DataContext

在PopupWindowAction里,把TestControl的DataContext绑定到Confirmation的Content:

<prism:PopupWindowAction IsModal="True" CenterOverAssociatedObject="True">
    <prism:PopupWindowAction.WindowContent>
        <local:TestControl DataContext="{Binding Content}"/>
    </prism:PopupWindowAction.WindowContent>
</prism:PopupWindowAction>

这样每个弹出窗口都会拥有独立的ViewModel,SelectedMode属性互不干扰,自然就不会出现之前的选中状态被取消的问题。

2. 确保ViewModel不是单例

如果你用了Prism的依赖注入容器,检查TestViewModel的注册方式,确保它是瞬态(每次请求创建新实例):

// 在Module或App.xaml.cs的RegisterTypes方法中
containerRegistry.Register<TestViewModel>();
// 绝对不要用 RegisterSingleton<TestViewModel>();

3. 检查EnumToBooleanConverter的实现

确保转换器是无状态的,不要维护任何静态变量,正确的实现应该是这样的:

public class EnumToBooleanConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null || parameter == null)
            return false;
        return value.Equals(parameter);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool isChecked && isChecked && parameter != null)
        {
            return Enum.Parse(targetType, parameter.ToString());
        }
        return Binding.DoNothing;
    }
}

验证方法

你可以在TestViewModel的构造函数里加个断点,每次弹出窗口时如果都能触发断点,说明每个窗口都有独立的ViewModel;如果只触发一次,那就是共用了同一个实例,需要调整创建方式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:58:22