diff --git a/src/BootstrapBlazor.Server/Components/Samples/MultiSelects.razor b/src/BootstrapBlazor.Server/Components/Samples/MultiSelects.razor index 1d29957a846..6a6ecb4a7a7 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/MultiSelects.razor +++ b/src/BootstrapBlazor.Server/Components/Samples/MultiSelects.razor @@ -325,26 +325,28 @@ private enum MultiSelectEnumFoo

1. 使用 OnQueryAsync 作为数据源

-
- +

2. 使用 Items 作为数据源

-
- +
diff --git a/src/BootstrapBlazor.Server/Components/Samples/MultiSelects.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/MultiSelects.razor.cs index cc926bd65b0..2f93ec157b0 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/MultiSelects.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/MultiSelects.razor.cs @@ -113,11 +113,12 @@ private enum MultiSelectEnumFoo [NotNull] private List? Foos { get; set; } - private string? _virtualItemString1; + private string? _virtualItemValue1; + private string? _virtualItemValue2; + private string? _virtualItemText1; + private string? _virtualItemText2; - private string? _virtualItemString2; - - private IEnumerable VirtualItems => Foos.Select(i => new SelectedItem(i.Name!, i.Name!)).ToList(); + private IEnumerable VirtualItems => Foos.Select(i => new SelectedItem(i.Id.ToString(), i.Name!)).ToList(); private string? _editString; private bool _isClearable = true; @@ -213,8 +214,10 @@ protected override void OnInitialized() Items = GenerateDataSource(DataSource); Foos = Foo.GenerateFoo(LocalizerFoo); - _virtualItemString1 = Foos[79].Name; - _virtualItemString2 = Foos[45].Name; + _virtualItemValue1 = $"{Foos[79].Id}, {Foos[78].Id}"; + _virtualItemValue2 = $"{Foos[45].Id}, {Foos[46].Id}"; + _virtualItemText1 = $"{Foos[79].Name}, {Foos[78].Name}"; + _virtualItemText2 = $"{Foos[45].Name}, {Foos[46].Name}"; } private static List GenerateItems() => @@ -482,6 +485,14 @@ private AttributeItem[] GetAttributes() => Type = "bool", ValueList = "true|false", DefaultValue = "false" + }, + new() + { + Name = nameof(MultiSelect.DefaultVirtualizeItemText), + Description = Localizer["MultiSelectsAttribute_DefaultVirtualizeItemText"], + Type = "string", + ValueList = " — ", + DefaultValue = " — " } ]; } diff --git a/src/BootstrapBlazor.Server/Components/Samples/Selects.razor.cs b/src/BootstrapBlazor.Server/Components/Samples/Selects.razor.cs index 4eb82111198..4c2eb39bbdf 100644 --- a/src/BootstrapBlazor.Server/Components/Samples/Selects.razor.cs +++ b/src/BootstrapBlazor.Server/Components/Samples/Selects.razor.cs @@ -423,6 +423,14 @@ private AttributeItem[] GetAttributes() => Type = "bool", ValueList = "true|false", DefaultValue = "false" + }, + new() + { + Name = nameof(Select.DefaultVirtualizeItemText), + Description = Localizer["SelectsDefaultVirtualizeItemText"], + Type = "string", + ValueList = " — ", + DefaultValue = " — " } ]; } diff --git a/src/BootstrapBlazor.Server/Locales/en-US.json b/src/BootstrapBlazor.Server/Locales/en-US.json index b4222f97bd4..63fe6cc4810 100644 --- a/src/BootstrapBlazor.Server/Locales/en-US.json +++ b/src/BootstrapBlazor.Server/Locales/en-US.json @@ -3031,7 +3031,8 @@ "MultiSelectVirtualizeIntro": "Set IsVirtualize to true enable virtual scroll for large data", "MultiSelectVirtualizeDescription": "Component virtual scrolling supports two ways of providing data through Items or OnQueryAsync callback methods", "MultiSelectsAttribute_ShowSearch": "Whether to display the search box", - "MultiSelectsAttribute_IsVirtualize": "Wether to enable virtualize" + "MultiSelectsAttribute_IsVirtualize": "Wether to enable virtualize", + "MultiSelectsAttribute_DefaultVirtualizeItemText": "The text string corresponding to the first load value when virtual scrolling is turned on is separated by commas" }, "BootstrapBlazor.Server.Components.Samples.Radios": { "RadiosTitle": "Radio", @@ -3208,7 +3209,8 @@ "SelectsOnInputChangedCallback": "Callback method for converting input text into corresponding Value in edit mode", "TextConvertToValueCallback": "Callback method when input text changes in edit mode", "SelectsIsEditable": "Whether editable", - "SelectsIsVirtualize": "Wether to enable virtualize" + "SelectsIsVirtualize": "Wether to enable virtualize", + "SelectsDefaultVirtualizeItemText": "The text string corresponding to the first load value when virtual scrolling is turned on is separated by commas" }, "BootstrapBlazor.Server.Components.Samples.Sliders": { "SlidersTitle": "Slider", diff --git a/src/BootstrapBlazor.Server/Locales/zh-CN.json b/src/BootstrapBlazor.Server/Locales/zh-CN.json index 38185aa07b4..5450fd520d7 100644 --- a/src/BootstrapBlazor.Server/Locales/zh-CN.json +++ b/src/BootstrapBlazor.Server/Locales/zh-CN.json @@ -3031,7 +3031,8 @@ "MultiSelectVirtualizeIntro": "通过设置 IsVirtualize 参数开启组件虚拟功能特性", "MultiSelectVirtualizeDescription": "组件虚拟滚动支持两种形式通过 Items 或者 OnQueryAsync 回调方法提供数据", "MultiSelectsAttribute_ShowSearch": "是否显示搜索框", - "MultiSelectsAttribute_IsVirtualize": "是否开启虚拟滚动" + "MultiSelectsAttribute_IsVirtualize": "是否开启虚拟滚动", + "MultiSelectsAttribute_DefaultVirtualizeItemText": "开启虚拟滚动时首次加载 Value 对应的文本字符串用逗号分割" }, "BootstrapBlazor.Server.Components.Samples.Radios": { "RadiosTitle": "Radio 单选框", @@ -3208,7 +3209,8 @@ "SelectsOnInputChangedCallback": "编辑模式下输入文本转换为对应 Value 回调方法", "TextConvertToValueCallback": "编辑模式下输入文本变化时回调方法", "SelectsIsEditable": "是否可编辑", - "SelectsIsVirtualize": "是否开启虚拟滚动" + "SelectsIsVirtualize": "是否开启虚拟滚动", + "SelectsDefaultVirtualizeItemText": "开启虚拟滚动时首次加载 Value 对应的文本字符串用逗号分割" }, "BootstrapBlazor.Server.Components.Samples.Sliders": { "SlidersTitle": "Slider 滑块", diff --git a/src/BootstrapBlazor/BootstrapBlazor.csproj b/src/BootstrapBlazor/BootstrapBlazor.csproj index 7001e10fdeb..40666cb0b8f 100644 --- a/src/BootstrapBlazor/BootstrapBlazor.csproj +++ b/src/BootstrapBlazor/BootstrapBlazor.csproj @@ -1,7 +1,7 @@  - 9.4.10 + 9.5.0-beta10 diff --git a/src/BootstrapBlazor/Components/Select/MultiSelect.razor.cs b/src/BootstrapBlazor/Components/Select/MultiSelect.razor.cs index 4e246e2630f..c59a459e7ba 100644 --- a/src/BootstrapBlazor/Components/Select/MultiSelect.razor.cs +++ b/src/BootstrapBlazor/Components/Select/MultiSelect.razor.cs @@ -112,6 +112,12 @@ public partial class MultiSelect [Parameter] public Func, Task>? OnSelectedItemsChanged { get; set; } + /// + /// Gets or sets the default virtualize items text. + /// + [Parameter] + public string? DefaultVirtualizeItemText { get; set; } + /// /// 获得/设置 全选按钮显示文本 /// @@ -158,6 +164,7 @@ public partial class MultiSelect [Parameter] [NotNull] public string? MinErrorMessage { get; set; } + [Inject] [NotNull] private IStringLocalizer>? Localizer { get; set; } @@ -167,7 +174,7 @@ public partial class MultiSelect private string? ScrollIntoViewBehaviorString => ScrollIntoViewBehavior == ScrollIntoViewBehavior.Smooth ? null : ScrollIntoViewBehavior.ToDescriptionString(); /// - /// OnParametersSet 方法 + /// /// protected override void OnParametersSet() { @@ -195,15 +202,15 @@ protected override void OnParametersSet() if (_lastSelectedValueString != _currentValue) { _lastSelectedValueString = _currentValue; - var list = _currentValue.Split(',', StringSplitOptions.RemoveEmptyEntries); SelectedItems.Clear(); if (IsVirtualize) { - SelectedItems.AddRange(list.Select(i => new SelectedItem(i, i))); + SelectedItems.AddRange(GetItemsByVirtualize()); } else { + var list = _currentValue.Split(',', StringSplitOptions.RemoveEmptyEntries); SelectedItems.AddRange(Rows.Where(item => list.Any(i => i.Trim() == item.Value))); } } @@ -232,6 +239,23 @@ protected override void OnAfterRender(bool firstRender) ToggleRow = nameof(ToggleRow) }); + private List GetItemsByVirtualize() + { + var ret = new List(); + var texts = new List(); + if (!string.IsNullOrEmpty(DefaultVirtualizeItemText)) + { + texts.AddRange(DefaultVirtualizeItemText.Split(',', StringSplitOptions.RemoveEmptyEntries)); + } + var values = CurrentValueAsString.Split(',', StringSplitOptions.RemoveEmptyEntries).ToList(); + for (int i = 0; i < values.Count; i++) + { + var text = i < texts.Count ? texts[i] : values[i]; + ret.Add(new SelectedItem(values[i], text)); + } + return ret; + } + private int _totalCount; private ItemsProviderResult _result; @@ -265,7 +289,7 @@ protected override async Task OnClearValue() } /// - /// FormatValueAsString 方法 + /// /// /// /// @@ -350,7 +374,7 @@ public async Task TriggerEditTag(string val) val = val.Trim(); if (OnEditCallback != null) { - ret = await OnEditCallback.Invoke(val); + ret = await OnEditCallback(val); } else if (!string.IsNullOrEmpty(val)) { diff --git a/test/UnitTest/Components/MultiSelectTest.cs b/test/UnitTest/Components/MultiSelectTest.cs index 67dd655fbfa..4561021c772 100644 --- a/test/UnitTest/Components/MultiSelectTest.cs +++ b/test/UnitTest/Components/MultiSelectTest.cs @@ -668,7 +668,7 @@ public void IsMarkupString_Ok() } [Fact] - public void IsVirtualize_Items() + public void DefaultVirtualizeItemText_Ok() { var cut = Context.RenderComponent>(pb => { @@ -677,19 +677,14 @@ public void IsVirtualize_Items() new("1", "Test1"), new("2", "Test2") }); - pb.Add(a => a.Value, "2"); + pb.Add(a => a.Value, "1,2"); + pb.Add(a => a.DefaultVirtualizeItemText, "Test1"); pb.Add(a => a.IsVirtualize, true); - pb.Add(a => a.RowHeight, 33f); - pb.Add(a => a.OverscanCount, 4); - }); - - cut.SetParametersAndRender(pb => pb.Add(a => a.ShowSearch, true)); - cut.InvokeAsync(async () => - { - // 搜索 T - cut.Find(".search-text").Input("T"); - await cut.Instance.ConfirmSelectedItem(0); }); + var items = cut.FindAll(".multi-select-items .multi-select-item"); + Assert.Equal(2, items.Count); + Assert.Equal("Test1", items[0].InnerHtml); + Assert.Equal("2", items[1].InnerHtml); } [Fact]