WINUI——复制原RadioButtion到新位置,出现"System.StackOverflowException"

问题现象

WINUI程序中,对UI进行了重构:添加了一个Grid,在Grid中将原来在这个页面中的超级管理员中的一些功能,添加到这个Grid里,以给普通的管理员admin在登陆到功能设置页面时使用;主要涉及两个RadioButton按钮,两个ToggleSwitch和一个ListView。

在将UI设计好并按原来的绑定关系绑定好,并以admin登陆到功能设置页面,进行初步的测试,当一点到RadioButton时,就出现了"System.StackOverflowException" 异常,如下图:

image

 

一些人看到上图,可能会有疑惑,为什么是在点击RadioButton时出现了异常,为什么报错截图上显示的是——ToggleButton?

因为RadioButton是ToggleButton的子类,其关系如下图,详细可参考MSDN

image

 

排查过程

由于仅是对UI进行了相应的重构,并未涉及到VM中代码的修改,这明显就是UI上绑定导致了死循环,从而导致溢出。

然,看来看去,也没有看出个所以然。

 

突然想到我是复制的RadioButton到当前普通的admin需要的Grid内,那么是不是意味着当前位置的RadioButton绑定值在改变后,会影响原来超级管理员位置的数据绑定?或者同时引起原来超级管理员位置的RadioButton也进行相同的操作?

想了下,前者是肯定的,这应该没有问题;而后者,则是不应该出现的。

 

于是仔细比对了普通管理员admin位置的RadioButton,普通位置与超级管理员位置的RadioButton竟然使用的是相同的GroupName。这就意味着普通管理员位置的RadioButton进行切换时,也会导致超级管理员位置的RadioButton进行对应响应,因为这4个RadioButton属于一个Group,一个Group中有且只有一个RadioButton是能选中的。

超级管理员使用的RadioButton:

                        <RadioButton
                            x:Name="OptionVoxelRender"
                            Content="体素渲染"
                            GroupName="rendering"
                            IsChecked="{x:Bind ViewModel.SurgicalPlanSettingDTO.IsMeshRendering, Mode=TwoWay, Converter={StaticResource ReverseBoolConverter}}"
                            IsEnabled="{x:Bind ViewModel.UserInfo.IsSuperAdmin, Mode=OneWay}" />
                        <RadioButton
                            x:Name="OptionMeshRender"
                            Content="Mesh渲染"
                            GroupName="rendering"
                            IsChecked="{x:Bind ViewModel.SurgicalPlanSettingDTO.IsMeshRendering, Mode=TwoWay}"
                            IsEnabled="{x:Bind ViewModel.UserInfo.IsSuperAdmin, Mode=OneWay}" />

 

普通管理员admin使用的RadioButton:

                    <RadioButton
                        x:Name="OptionNVoxelRender"
                        Content="体素渲染"
                        GroupName="rendering"
                        IsChecked="{x:Bind ViewModel.SurgicalPlanSettingDTO.IsMeshRendering, Mode=TwoWay, Converter={StaticResource ReverseBoolConverter}}"
                        IsEnabled="{x:Bind ViewModel.UserInfo.IsAdminShow}" />
                    <RadioButton
                        x:Name="OptionNMeshRender"
                        Content="Mesh渲染"
                        GroupName="rendering"
                        IsChecked="{x:Bind ViewModel.SurgicalPlanSettingDTO.IsMeshRendering, Mode=TwoWay}"
                        IsEnabled="{x:Bind ViewModel.UserInfo.IsAdminShow}" />

 

原因分析

一个RadioButton组中,有且只有一个RadioButton是能选中的,若在不同的地方用相同的组名,那么势必造成一些问题。

 

也就是说由于在这个页面中普通管理员与超级管理员中的RadioButton使用的是相同的属性进行的通知绑定,那么一切换也就会造成循环引用出现的溢出问题了。

 

此处的问题就是admin处的地方改变会导致VM中进行IsMeshRendering的更新,它一更新又会导致superAdmin位置的数据更新(双向绑定),superAdmin的地方又会触发IsChecked事件,然后导致VM中又进行更新,同时返回通知admin处的RadioButton进行更新……如此循环。

解决方案

解决就比较简单了,只需要将普通管理员处RadioButton的组名修改一下,保证与超级管理员处的组名不一样即可。

建议

细心很重要,否则就算老鸟,也会犯这种低级错误。

 

posted @ 2025-09-24 11:50  盛沧海  阅读(13)  评论(0)    收藏  举报