Skip to content

Select 组件是否要重复触发 OnSelectedItemChanged 讨论 #7409

Closed

Description

@water1983

Is there an existing issue for this?

  • I have searched the existing issues

Describe the bug

<Select IsPopover="true" IsDisabled="sSelectIsDisabled"
        TValue="string" Items="sSelectItems"
        @bind-Value="sSelectedValue"
        OnSelectedItemChanged="sSelect_OnSelectedItemChanged" Color="Color.Dark" />

在后台代码中

sSelectedItems=[];
sSelectedItems.Add(new SelectedItem
                            {
                                Text = "T1",
                                Value = "T1"
                            });

sSelectedValue=null;//不触发OnSelectedItemChanged
sSelectItems.Clean();
sSelectedItems.Add(new SelectedItem
                            {
                                Text = "T1",
                                Value = "T1"//如果这里跟上面的不一样,则sSelectedValue = sSelectedItems.First();会触发
                            });
sSelectItems.Add..一组新的,但第一个选项的文本值,和置为null之前的一样.

sSelectedValue = sSelectedItems.First();//不触发OnSelectedItemChanged
(如果第一个选项的文本值,和置为null之前的不一样,会触发OnSelectedItemChanged)

我看Select的代码判定是否触发OnSelectedItemChanged有个内部变量_lastSelectedValueString
但无论是将Value置为null还是清空Items的时候都不会改变这个_lastSelectedValueString,值依然维持在第一次选择后

Expected Behavior

Value置为null时清空上次选择的记忆,或者给个选项能够清空。

Interactive render mode

Interactive Server (Interactive server-side rendering (interactive SSR) using Blazor Server)

Steps To Reproduce

<Select IsPopover="true" IsDisabled="sSelectIsDisabled"
        TValue="string" Items="sSelectItems"
        @bind-Value="sSelectedValue"
        OnSelectedItemChanged="sSelect_OnSelectedItemChanged" Color="Color.Dark" />

在后台代码中

sSelectedItems=[];
sSelectedItems.Add(new SelectedItem
                            {
                                Text = "T1",
                                Value = "T1"
                            });
.......
sSelectedValue=null;//不触发OnSelectedItemChanged
sSelectItems.Clean();
sSelectedItems.Add(new SelectedItem
                            {
                                Text = "T1",
                                Value = "T1"//如果这里跟上面的不一样,则sSelectedValue = sSelectedItems.First();会触发
                            });
sSelectItems.Add.....一组新的,但第一个选项的文本值,和置为null之前的一样.

sSelectedValue = sSelectedItems.First();//不触发OnSelectedItemChanged

(如果第一个选项的文本值,和置为null之前的不一样,会触发OnSelectedItemChanged)

我看Select的代码判定是否触发OnSelectedItemChanged有个内部变量_lastSelectedValueString
但无论是将Value置为null还是清空Items的时候都不会改变这个_lastSelectedValueString,值依然维持在第一次选择后

Exceptions (if any)

No response

.NET Version

NET9.0

Anything else?

No response

Activity

  1. bb-auto commented on Dec 25, 2025

    @bb-auto

    @water1983 Thank you for filing this issue. In order for us to investigate this issue, please provide a minimalistic repro project that illustrates the problem.

  2. added this to the v10.1.0 milestone on Dec 25, 2025
  3. ArgoZhang commented on Dec 25, 2025

    @ArgoZhang
    Member

    @water1983 感谢提交代码,马上修复一下,代码尽量不要贴上来,上传示例工程(删除 bin obj),如果要贴也要格式化,不然没有办法看。谢谢啦

  4. ArgoZhang commented on Dec 25, 2025

    @ArgoZhang
    Member

    @water1983 Issue 中的代码我已经帮你格式化了。这样别人来看也很容易阅读

  5. ArgoZhang commented on Dec 25, 2025

    @ArgoZhang
    Member

    @water1983 这个问题我看了一下源码,不建议触发 OnSelectedItemChanged 甚至 OnValueChanged 也不会触发的,原因有点复杂,我打字说不清楚,我有看了微软的组件库源码,这种更改也是都不触发的。

  6. water1983 commented on Dec 25, 2025

    @water1983
    ContributorAuthor

    @water1983 这个问题我看了一下源码,不建议触发 OnSelectedItemChanged 甚至 OnValueChanged 也不会触发的,原因有点复杂,我打字说不清楚,我有看了微软的组件库源码,这种更改也是都不触发的。

    好的,感谢快速回复。

    那看来只能在sSelectedValue = sSelectedItems.First();后代码里直接去调OnSelectedItemChanged了,不过会有时候调一遍有时候调两遍(如前文,sSelectedItems.First()中的内容与清空之前的选择项的内容不同时,sSelectedItems.First()本身会调一次),只能在变更Items的时候暂时解绑OnSelectedItemChanged事件了,手动调完再重新绑定。

  7. ArgoZhang commented on Dec 25, 2025

    @ArgoZhang
    Member

    @water1983 一样的道理啊。微软的路子是走的 mvvm 模式,就是 UI 的人机交互会驱动后台数据的改变,你的逻辑直接给绑定的变量赋值了。

    望再理解一下

    但是如果有时候一次有时候二次,这感觉是有问题的。希望给出例子,我来排查一下问题点,可能有 bug

  8. water1983 commented on Dec 25, 2025

    @water1983
    ContributorAuthor

    BootstrapBlazorTestSelect.zip

    @ArgoZhang 大佬看下,不知道能否表达清楚

    测试方法在Index页

  9. ArgoZhang commented on Dec 26, 2025

    @ArgoZhang
    Member

    @water1983 我运行了代码,我没发现问题点,都符合预期啊

    能否写一下

    预期是什么,实际是什么 这种测试步骤与报告,我针对性测试一下

  10. water1983 commented on Dec 26, 2025

    @water1983
    ContributorAuthor

    @ArgoZhang 运行效果为,第一个按钮,点第一次的时候,OnSelectedItemChanged会触发,点第二次的时候,不触发。

    预期是每次点第一个按钮,都触发OnSelectedItemChanged

    原理是,第一个按钮里,每次都先将Value改为null,将Items清空,并重新添加Items,并自动选择第一项,同时要触发第一项里的OnSelectedItemChanged(每次重新添加并选择第一项后都要触发)。
    实际业务场景,是Items会根据其他选项进行联动,所以点按钮时会变更Items的内容。但有可能变更后的Items和变更前一样。虽然一样, 依然需要触发第一项里的OnSelectedItemChanged,因为里面有另一些内容的初始化和启动代码。

    我看到Select源码中,判断是否触发OnSelectedItemChanged有一个内部字段_lastSelectedValueString,但是在赋值Value为null或者清空Items的时候,这个字段的内容并没有改变,依然维持上一次的Value。所以导致Value设置为null和清空Items后再添加Items,如果Items.First().Value与_lastSelectedValueString相同,就不会触发OnSelectedItemChanged了。

  11. ArgoZhang commented on Dec 26, 2025

    @ArgoZhang
    Member

    @water1983

    第一个问题为什么两次都要触发 OnSelectedItemChanged 呢?第二次明明没有改变啊?组件内部认的是 Value 我理解你的意思

    你的逻辑是 Value1 => Null => Value1 但是你中间没有更新 UI,对组件而言始终是 Value1 所以选项没有改变。

    你的需求正确的逻辑应该是这样

    选中 Value1 选项后,不是赋值 null 而是赋值一个 "" 的候选项,通知 UI (StateHasChanged)然后再赋值 Value1 再通知 UI (StateHasChanged) 即可实现你的需求

    注意点你候选项中要有 "" 选项

    还有一个点,你日常开发,自己代码主动更改了下拉框数据源以及选项,就走内部逻辑啊,为什么要依赖 UI 的变换再去改变另外一个数据逻辑?我理解你的做法,但是这样做你想想是不是效率非常低,你改变第一个下拉框的东西,要让 UI 去触发,然后又去走后台逻辑改变第二个下拉框的 UI 然后再去变更 UI,为什么不是一次到位,后台改变一次数据, UI 更新一次呢?逻辑清晰,效率还高,后台数据改变一次,UI更新一次(多个下拉框一次刷新)

  12. water1983 commented on Dec 26, 2025

    @water1983
    ContributorAuthor

    @ArgoZhang
    1、因为业务需要,不希望用户能自己选择“”选项
    2、这个Items的变化是其他变化关联引起的,对用户来讲,他们是点了一个其他按钮后(假设他叫切换车间),关联的发生了下拉框里的内容变化,同时对应的设备要启动(由OnSelectedItemChanged里)。
    3、从功能的模块化考虑,我不能在切换车间的按钮的代码里去启动设备啊(因为车间内的设备列表是要重新给Items赋值的时候从数据库读的,切换车间按钮也不知道该“启动”哪个设备),出现这一次和上一次Select里的Value相同的原因,只是两个不同的车间第一个设备名称相同而已,对用户这个操作,不存在需要“维持”上一个选项的概念,这就是一次新的选择(虽然Value相同),并且这个选择是由切换车间按钮带来的,而不是重新选择下拉框带来的。

  13. j4587698 commented on Dec 26, 2025

    @j4587698
    Collaborator

    但是这个对于组件来说,他就是相同的,如果这里改了,那么你下拉选项里重新选择相同的内容,它也会触发OnSelectedItemChanged事件,这个明显是不合理的

  14. ArgoZhang commented on Dec 26, 2025

    @ArgoZhang
    Member

    @water1983 Select 组件目前就是根据 Value 值判断的。而且这个值是 值类型,所以无法满足你的需求,你可以试试看 SelectGeneric 组件,这个组件 Value 是 Class 这样就可以做到两次 Class.Id 一样也可以触发,因为 Class 不是同一个实例了

  15. water1983 commented on Dec 26, 2025

    @water1983
    ContributorAuthor

    但是这个对于组件来说,他就是相同的,如果这里改了,那么你下拉选项里重新选择相同的内容,它也会触发OnSelectedItemChanged事件,这个明显是不合理的

    我说的是将value改为null后,再改相同值时,触发。这个行为和重复选择相同内容不一样(重复选择并没有改null),并不会导致重复选择相同内容重复触发。

  16. water1983 commented on Dec 26, 2025

    @water1983
    ContributorAuthor

    @water1983 Select 组件目前就是根据 Value 值判断的。而且这个值是 值类型,所以无法满足你的需求,你可以试试看 SelectGeneric 组件,这个组件 Value 是 Class 这样就可以做到两次 Class.Id 一样也可以触发,因为 Class 不是同一个实例了

    好的,谢谢。我试下这个。

  17. changed the title [-]bug(Select): Select在代码中将Value改为null,不触发OnSelectedItemChanged[/-] [+]Select 组件是否要重复触发 OnSelectedItemChanged 讨论[/+] on Dec 26, 2025
  18. locked and limited conversation to collaborators on Dec 26, 2025
  19. converted this issue into a discussion #7421 on Dec 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions