Compare commits
213 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
481be3a5b2 | ||
|
|
4fd5a23ecd | ||
|
|
a4d112e0a4 | ||
|
|
305283993c | ||
|
|
e6bdaae6ce | ||
|
|
ce64046690 | ||
|
|
d7547b76a2 | ||
|
|
dbaebf2c2e | ||
|
|
8fd8689969 | ||
|
|
b038291382 | ||
|
|
a0fb963bc3 | ||
|
|
3b37589ef9 | ||
|
|
4e082ca7da | ||
|
|
7549240abf | ||
|
|
f0f2c733da | ||
|
|
35c550bfa3 | ||
|
|
5638f86466 | ||
|
|
795d39a07d | ||
|
|
41a1382e76 | ||
|
|
ac4e5c03c6 | ||
|
|
28aacd755f | ||
|
|
bebdf4e7c6 | ||
|
|
2fb689e987 | ||
|
|
98f945121b | ||
|
|
4be6ccbc92 | ||
|
|
bc0ba0733c | ||
|
|
d91bd93554 | ||
|
|
818bea5062 | ||
|
|
b12513bbe6 | ||
|
|
314b837d63 | ||
|
|
253618307e | ||
|
|
ede70e7010 | ||
|
|
22b472fab6 | ||
|
|
bbc442b0f6 | ||
|
|
c6a51e3e29 | ||
|
|
866824d7ea | ||
|
|
bce5422c24 | ||
|
|
b81130da87 | ||
|
|
cc0e92a511 | ||
|
|
7166fceed1 | ||
|
|
69d26ba5af | ||
|
|
6246d0792f | ||
|
|
c608060f44 | ||
|
|
b85a89a671 | ||
|
|
08b3745b8d | ||
|
|
2d57844dce | ||
|
|
234e7b3f17 | ||
|
|
71915a8669 | ||
|
|
b57b70855e | ||
|
|
aaa8d5f2d6 | ||
|
|
7c24ec65a2 | ||
|
|
a7b3bf4105 | ||
|
|
1feb75425e | ||
|
|
8b1fd0cc7c | ||
|
|
e49bfaab5f | ||
|
|
1711200a39 | ||
|
|
22e56afff6 | ||
|
|
fe9d30a0a2 | ||
|
|
2761d641d0 | ||
|
|
39bf5c595b | ||
|
|
c00fab53d4 | ||
|
|
4b24062b44 | ||
|
|
72b491488e | ||
|
|
e20fbd193f | ||
|
|
2b55cbb8ed | ||
|
|
12ba06f35c | ||
|
|
b8ff10d26b | ||
|
|
2edcc489ca | ||
|
|
0bb2ae50a4 | ||
|
|
ec234e8d3c | ||
|
|
99a501d5d2 | ||
|
|
1af4e6308c | ||
|
|
958a9d6ae0 | ||
|
|
12b49f6fa5 | ||
|
|
bb054152be | ||
|
|
bdadf3a83c | ||
|
|
e52a236c26 | ||
|
|
4ba98c0471 | ||
|
|
d7f6ef805a | ||
|
|
d8c9f17321 | ||
|
|
b157b76610 | ||
|
|
918266778a | ||
|
|
2cdea01d9e | ||
|
|
a2947ffd2c | ||
|
|
252d9a713f | ||
|
|
252187a361 | ||
|
|
8420543845 | ||
|
|
2dab2c3005 | ||
|
|
cd4322cc20 | ||
|
|
6217855c84 | ||
|
|
bfc54e86b2 | ||
|
|
f06d7feda1 | ||
|
|
dc10c2ad2d | ||
|
|
8d9e4bc00a | ||
|
|
aa3de4ee74 | ||
|
|
0f68ef4022 | ||
|
|
657ed3cf69 | ||
|
|
36fb575512 | ||
|
|
4b6e0edaf5 | ||
|
|
6a28892db4 | ||
|
|
d299f8b4cf | ||
|
|
e036b4ee7c | ||
|
|
ab8b333e14 | ||
|
|
d9bbf0853a | ||
|
|
8bf4f7aa8d | ||
|
|
9b364ae87d | ||
|
|
3e2e6e0198 | ||
|
|
e4a3a886c7 | ||
|
|
c51c2b67e9 | ||
|
|
743ae67586 | ||
|
|
10105843ef | ||
|
|
de240b9d1c | ||
|
|
7ac372fbc5 | ||
|
|
6fa9cd4916 | ||
|
|
0d2d01e4d2 | ||
|
|
48cfc05834 | ||
|
|
07c9da99e1 | ||
|
|
3fc6c80c86 | ||
|
|
f8dcc0b6b2 | ||
|
|
73a34d169d | ||
|
|
bdda880aa5 | ||
|
|
62cae7a29e | ||
|
|
abbbfdd0a3 | ||
|
|
c1e6fffdee | ||
|
|
324455eedd | ||
|
|
4941e31bb7 | ||
|
|
4a15cd7608 | ||
|
|
437b4d96c7 | ||
|
|
7d740425e7 | ||
|
|
8155325018 | ||
|
|
3555963903 | ||
|
|
05246ee852 | ||
|
|
f215ecec7b | ||
|
|
68283dda24 | ||
|
|
ad35968019 | ||
|
|
3610c1e89f | ||
|
|
a03d6d4869 | ||
|
|
5517556bb9 | ||
|
|
37c562d176 | ||
|
|
b27ed69ada | ||
|
|
d37f192a66 | ||
|
|
ecf6bd1464 | ||
|
|
52462a457c | ||
|
|
c0a19c9596 | ||
|
|
82366af97a | ||
|
|
e7c9a879e9 | ||
|
|
9d316d6abf | ||
|
|
8614831edc | ||
|
|
3fbf39878a | ||
|
|
74e4268f01 | ||
|
|
e592416919 | ||
|
|
b525035da4 | ||
|
|
ec3a123bfb | ||
|
|
5f121ec1ce | ||
|
|
fbe7fd228b | ||
|
|
72420740ea | ||
|
|
11dace83c6 | ||
|
|
82ca776f88 | ||
|
|
978279f363 | ||
|
|
18b1c3bf86 | ||
|
|
e5cf86ea4f | ||
|
|
c162fc28e5 | ||
|
|
5ea38c99d1 | ||
|
|
ca286e8e99 | ||
|
|
131473a5c0 | ||
|
|
eb992f8ada | ||
|
|
c04a142697 | ||
|
|
120c22ccb3 | ||
|
|
6cd9acf32d | ||
|
|
f722ad07fe | ||
|
|
de747e1bc2 | ||
|
|
d05b6bba8c | ||
|
|
a28667f25e | ||
|
|
23e385b107 | ||
|
|
c50d429102 | ||
|
|
a9ccb16e19 | ||
|
|
49ecc6cc27 | ||
|
|
e24d35e3b7 | ||
|
|
6c6af4a444 | ||
|
|
e84bbc3e4d | ||
|
|
4b5524c583 | ||
|
|
8caca1b0e5 | ||
|
|
fa56698d87 | ||
|
|
3b24f9ccc7 | ||
|
|
6d35296b37 | ||
|
|
ca6ece9ac8 | ||
|
|
7f78203481 | ||
|
|
14668753de | ||
|
|
4aec42a6ae | ||
|
|
1d106f0261 | ||
|
|
4cb72b5584 | ||
|
|
09b750b57f | ||
|
|
10b205b67d | ||
|
|
288e32da5e | ||
|
|
2b429cb9e0 | ||
|
|
5f9d9388a8 | ||
|
|
29bbffe68e | ||
|
|
217cc078ca | ||
|
|
d6b05efc5d | ||
|
|
dfbc622273 | ||
|
|
33557825cf | ||
|
|
ee21d06ffa | ||
|
|
9088449686 | ||
|
|
d44a8a59b8 | ||
|
|
fefaa2ba00 | ||
|
|
175cd55b8b | ||
|
|
3b0314026b | ||
|
|
7053d7345d | ||
|
|
1bb9c2aa51 | ||
|
|
9b39bbcb5e | ||
|
|
98d00a409e | ||
|
|
f08b573e8f | ||
|
|
9bb79547e2 |
@@ -64,8 +64,8 @@ dotnet_style_explicit_tuple_names = true:suggestion
|
||||
dotnet_style_null_propagation = true:suggestion
|
||||
dotnet_style_coalesce_expression = true:suggestion
|
||||
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:silent
|
||||
dotnet_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_tuple_names = true:suggestion
|
||||
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
|
||||
dotnet_style_prefer_auto_properties = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
|
||||
dotnet_style_prefer_conditional_expression_over_return = true:silent
|
||||
|
||||
26
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: Build Project
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.202
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
NUGET_API_KEY: ${{secrets.NUGET_API_KEY}}
|
||||
run: |
|
||||
dotnet restore src/BootstrapBlazor --no-cache
|
||||
dotnet build src/BootstrapBlazor
|
||||
2
.github/workflows/pack.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.201
|
||||
dotnet-version: 5.0.202
|
||||
|
||||
- name: Publish to Nuget
|
||||
env:
|
||||
|
||||
2
.github/workflows/publish.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.201
|
||||
dotnet-version: 5.0.202
|
||||
|
||||
- name: Publish wasm
|
||||
run: |
|
||||
|
||||
2
.github/workflows/release.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.201
|
||||
dotnet-version: 5.0.202
|
||||
|
||||
- name: Publish to Nuget
|
||||
env:
|
||||
|
||||
@@ -36,6 +36,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "appveyor", "appveyor", "{1E
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "github", "github", "{F0754254-903C-411B-972C-EC91254B4A67}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.github\workflows\build.yml = .github\workflows\build.yml
|
||||
.github\workflows\deploy.yml = .github\workflows\deploy.yml
|
||||
.github\workflows\pack.yml = .github\workflows\pack.yml
|
||||
.github\workflows\publish.yml = .github\workflows\publish.yml
|
||||
@@ -65,9 +66,6 @@ EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTest", "test\UnitTest\UnitTest.csproj", "{190F25CF-C6F9-4964-97E9-F6A912D527AE}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "extensions", "extensions", "{22328011-53B3-447A-B781-AC3C196B2847}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
src\Extensions\Directory.Build.props = src\Extensions\Directory.Build.props
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "wasm", "wasm", "{C8E79F4C-8C55-4E13-96B5-3D2BD6A07B74}"
|
||||
EndProject
|
||||
|
||||
90
CHANGELOG.zh-CN.md
Normal file
@@ -0,0 +1,90 @@
|
||||
<h1 align="center">Bootstrap Blazor 组件库</h1>
|
||||
|
||||
<div align="center">
|
||||
<h2>一套基于 Bootstrap 和 Blazor 的企业级组件库</h2>
|
||||
|
||||
|
||||
[](https://www.nuget.org/packages/BootstrapBlazor/)
|
||||
[](https://www.nuget.org/packages/BootstrapBlazor/)
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor)
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
### 发布周期
|
||||
|
||||
- 主版本号:与 Microsoft .NET 主版本号一致
|
||||
- 次版本号:与 Microsoft .NET 次版本号一致
|
||||
- 修订版本号:每周四发布正式版(翻车紧急修复会跳版本号)日常每天发布新功能测试版本或者修复 BUG 测试版本 beta-##
|
||||
|
||||
---
|
||||
|
||||
### 5.0.22
|
||||
|
||||
`2021-03-24`
|
||||
|
||||
#### 增加功能
|
||||
|
||||
- !1193 feat(#I3CQYI): Table 组件编辑按钮增加回调委托 [#I3CQYI](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1193)
|
||||
- !1192 feat(#I3CQY7): 增加 Row 组件用于栅格系统布局 [#I3CQY7](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1192)
|
||||
- !1191 feat(#I3CQXQ): 自动生成标签 AutoGenerateColumn 增加 ComponentType 属性用于自定义呈现组件 [#I3CQXQ](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1191)
|
||||
- !1188 feat(#I3CQY7): Switch 组件适配 Row 组件支持 row form-row form-inline 三种模式 [#I3CQY7](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1188)
|
||||
- !1187 feat(#I3CPJ8): Select 组件适配 Row 组件支持 row form-row form-inline 三种模式 [#I3CPJ8](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1187)
|
||||
- !1172 feat(#I3CFJS): Table 组件树形数据支持 CRUD 并且保持编辑前展开收缩状态 [#I3CFJS](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1172)
|
||||
- !1173 feat(#I3CBQT): 增加演示网站 wasm 模式对浏览器是否兼容性提示功能 [#I3CBQT](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1173)
|
||||
- !1171 feat(#I3CBI6): DataAnnotation 支持复杂类型的验证 [#I3CBI6](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1171)
|
||||
- !1167 feat(#I3C6GH): Table 组件展开树形数据是增加 Spin 动画效果 [#I3C6GH](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1167)
|
||||
|
||||
#### 问题修复
|
||||
|
||||
- !1189 fix(#I3CPLZ): 更新 EFCore 数据注入服务获取记录总数逻辑 [#I3CPLZ](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1189)
|
||||
- !1185 fix(#I3CFAS): 修复 EFCore 数据注入服务排序导致递归循环引用问题 [#I3CFAS](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1185)
|
||||
- !1183 fix(#I3CF4K): 更新 EFCore 数据注入服务使服务生命周期内部与参数一致默认 Scope [#I3CF4K](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1183)
|
||||
- !1178 fix(#I3CCK1): 修复全局配置 SwalDelay 参数在 Swal 组件中未生效问题 [#I3CCK1](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1178)
|
||||
- !1177 fix(#I3CCIQ): 修复全局配置 MessageDelay 参数在 Message 组件中未生效问题 [#I3CCIQ](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1177)
|
||||
- !1175 fix(#I3CBSW): 修复 Timer 计时器组件不兼容 wasm 模式问题 [#I3CBSW](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1175)
|
||||
- !1168 fix(#I3C8PH): 修复 Tab 组件首次加载时活动标签页蓝色火柴棍特效不能正常呈现问题 [#I3C8PH](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1168)
|
||||
- !1163 fix(#I3C2W4): 修复内置数据服务导致高级搜索默认高亮状态问题 [#I3C2W4](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1163)
|
||||
- !1161 fix(#I3C205): 更新 Switch 组件点击事件触发组件 [#I3C205](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1161)
|
||||
|
||||
#### 示例更新
|
||||
|
||||
- !1190 docs(#I3CQXN): 更新 Table 组件明细行示例代码
|
||||
- !1182 docs(#I3CF12): 更新 Table 组件更新固定列示例代码
|
||||
- !1169 docs(#I3C8Q3): 更新 dialog 示例代码
|
||||
- !1166 docs(#I3C4HV): 更新 Table 组件固定表头示例代码
|
||||
- !1165 docs(#I3C4F0): 更新 Table 组件多表头示例代码
|
||||
|
||||
#### 性能优化
|
||||
|
||||
- !1186 perf(#I3CPID): 优化 ValidateForm 组件提高内部性能 [#I3CPID](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1186)
|
||||
- !1170 refactor(#I3CA0I): DynamicComponent 改名为 BootstrapDynamicComponent [#I3CA0I](https://gitee.com/LongbowEnterprise/BootstrapBlazor/pulls/1170)
|
||||
|
||||
|
||||
### 5.0.21
|
||||
|
||||
`2021-03-18`
|
||||
|
||||
* !1158 feat(#I3BULP): Table 组件增加数据服参数未设置时使用全局注入数据服务
|
||||
* !1157 feat(#I3BUL0): MultiSelect 组件支持双向绑定数组类型
|
||||
* !1155 feat(#I3BNXX): ValidateForm 组件增加 ValidateAllProperties 参数是否开启检查所有字段默认 false 仅检查表单中的绑定字段
|
||||
* !1154 feat(#I3BN0L): ValidateForm 组件增加 SetError 方法可主动设置绑定字段提示信息
|
||||
* !1153 feat(#I3BKXC): 优化 Upload 组件 ButtonUpload 模式上传失败后鼠标悬停图标
|
||||
* !1152 fix(#I3ALSP): 修复 Upload 组件 ShowProgress 与 IsMultiple 参数共同使用时出错问题
|
||||
* !1151 fix(#I3BGMV): 修复 Table 组件固定列后选中行样式被遮挡问题
|
||||
* !1147 fix(#I3AB7H): Upload 组件上传中增加 Spin 动画
|
||||
* !1145 fix(#I3BEBQ): 修复 Cascader 组件选中项样式
|
||||
* !1144 fix(#I3BBNS): 修复 Table 组件加载树形数据后与 ClickToSelect 参数冲突问题
|
||||
* !1143 perf(#I3BBMK): 优化 SweetAlert 组件内部弹窗性能
|
||||
* !1142 feat(#I3BADG): Dialog 组件支持无限弹窗
|
||||
* !1140 fix(#I3B9GU): 修复 Cascader 组件选择后显示文字不更新问题
|
||||
* !1139 feat(#I3B8RN): 演示站点增加切换主题功能
|
||||
* !1138 feat(#I3B8FX): Table 组件增加 ShowErrorToast 参数用于控制是否显示操作提示弹窗
|
||||
* !1137 feat(#I3B7UV): 新增 Cascader 组件
|
||||
* !1136 fix(#I3B502): 修复 Table 组件 ClickToSelect 属性与扩展操作按钮冲突问题
|
||||
* !1134 fix(#I3B50S): 修复 Table 组件树形数据点击节点无刷新问题
|
||||
* !1131 docs(#I3B1VU): Table 组件更新分页示例
|
||||
* !1130 feat(#I3B1VL): EditorForm 组件自动布局支持 Textarea 组件类型
|
||||
* !1128 fix(#I3AZOI): 修复 Menu 组件顶栏超过 5 个子菜单时样式不正确问题
|
||||
* !1127 perf(#I3AYCH): 优化 Dialog 组件性能阻止点击关闭等按钮导致子组件二次渲染问题
|
||||
@@ -1,5 +1,6 @@
|
||||
<Project>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<Copyright>Argo Zhang</Copyright>
|
||||
<Authors>Argo Zhang(argo@163.com)</Authors>
|
||||
<Company>Longbow</Company>
|
||||
|
||||
8
NuGet.Config
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="azure" value="https://nuget.cdn.azure.cn/v3/index.json" />
|
||||
<add key="cnblogs" value="https://nuget.cnblogs.com/v3/index.json" />
|
||||
<add key="huawei" value="https://repo.huaweicloud.com/repository/nuget/v3/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -1,15 +1,15 @@
|
||||
<h1 align="center">Bootstrap Blazor Component</h1>
|
||||
<h1 align="center">Bootstrap Blazor Component</h1>
|
||||
|
||||
<div align="center">
|
||||
<h2>A set of enterprise-class UI components based on Bootstrap and Blazor.</h2>
|
||||
|
||||
|
||||
[](https://github.com/ArgoZhang/BootstrapAdmin/actions?query=workflow%3A%22Auto+Build+CI%22+branch%3Amaster)
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor/actions?query=workflow%3A%22Build+Project%22+branch%3Amain)
|
||||
[](https://www.nuget.org/packages/BootstrapBlazor/)
|
||||
[](https://www.nuget.org/packages/BootstrapBlazor/)
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor/blob/master/LICENSE)
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor/blob/main/LICENSE)
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor)
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor)
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor)
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
# Bootstrap Blazor Component
|
||||
<h1 align="center">Bootstrap Blazor 组件库</h1>
|
||||
|
||||
<div align="center">
|
||||
<h2>一套基于 Bootstrap 和 Blazor 的企业级组件库</h2>
|
||||
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor/actions?query=workflow%3A%22Build+Project%22+branch%3Amain)
|
||||
[](https://www.nuget.org/packages/BootstrapBlazor/)
|
||||
[](https://www.nuget.org/packages/BootstrapBlazor/)
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor/blob/main/LICENSE)
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor)
|
||||
[](https://github.com/ArgoZhang/BootstrapBlazor)
|
||||
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
<a href="README.md">English</a> | <span>中文</span>
|
||||
|
||||
@@ -29,8 +43,16 @@ Blazor 是一个使用 .NET 生成交互式客户端 Web UI 的框架:
|
||||
3. 获取本项目代码 [BootstrapBlazor](https://gitee.com/LongbowEnterprise/BootstrapBlazor)
|
||||
|
||||
## 相关资源
|
||||
|
||||
- [Blazor 官方文档](https://docs.microsoft.com/zh-cn/aspnet/core/blazor/?WT.mc_id=DT-MVP-5004174)
|
||||
- [MS Learn 平台 Blazor 教程](https://docs.microsoft.com/zh-cn/learn/modules/build-blazor-webassembly-visual-studio-code/?WT.mc_id=DT-MVP-5004174)
|
||||
- [生成 Blazor Web 应用](https://docs.microsoft.com/zh-cn/learn/modules/build-blazor-webassembly-visual-studio-code/?WT.mc_id=DT-MVP-5004174)
|
||||
- [什么是 Blazor](https://docs.microsoft.com/zh-cn/learn/modules/build-blazor-webassembly-visual-studio-code/2-understand-blazor-webassembly?WT.mc_id=DT-MVP-5004174)
|
||||
- [练习 - 配置开发环境](https://docs.microsoft.com/zh-cn/learn/modules/build-blazor-webassembly-visual-studio-code/3-exercise-configure-enviromnent?WT.mc_id=DT-MVP-5004174)
|
||||
- [Blazor 组件](https://docs.microsoft.com/zh-cn/learn/modules/build-blazor-webassembly-visual-studio-code/4-blazor-components?WT.mc_id=DT-MVP-5004174)
|
||||
- [练习 - 添加组件](https://docs.microsoft.com/zh-cn/learn/modules/build-blazor-webassembly-visual-studio-code/5-exercise-add-component?WT.mc_id=DT-MVP-5004174)
|
||||
- [数据绑定和事件](https://docs.microsoft.com/zh-cn/learn/modules/build-blazor-webassembly-visual-studio-code/6-csharp-razor-binding?WT.mc_id=DT-MVP-5004174)
|
||||
- [练习 - 数据绑定和事件](https://docs.microsoft.com/zh-cn/learn/modules/build-blazor-webassembly-visual-studio-code/7-exercise-razor-binding?WT.mc_id=DT-MVP-5004174)
|
||||
- [总结](https://docs.microsoft.com/zh-cn/learn/modules/build-blazor-webassembly-visual-studio-code/8-summary?WT.mc_id=DT-MVP-5004174)
|
||||
|
||||
## QQ交流群
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
cd ~/BootstrapBlazor
|
||||
git pull
|
||||
dotnet restore --no-cache
|
||||
dotnet publish src/BootstrapBlazor.WebConsole -c Release
|
||||
|
||||
systemctl stop ba.blazor
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsWebProject>true</IsWebProject>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -10,7 +9,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Longbow.Tasks" Version="5.0.0" />
|
||||
<PackageReference Include="Longbow.Tasks" Version="5.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -6,6 +6,7 @@ using BootstrapBlazor.Shared;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -26,10 +27,17 @@ namespace BootstrapBlazor.Server.Controllers.Api
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
public Task<string> Get([FromQuery] string fileName, [FromServices] HttpClient client, [FromServices] IOptions<WebsiteOptions> options)
|
||||
public async Task<string> Get([FromQuery] string fileName, [FromServices] HttpClient client, [FromServices] IOptions<WebsiteOptions> options)
|
||||
{
|
||||
var ret = "";
|
||||
client.BaseAddress = new Uri(options.Value.RepositoryUrl);
|
||||
return client.GetStringAsync(fileName);
|
||||
try
|
||||
{
|
||||
ret = await client.GetStringAsync(fileName);
|
||||
}
|
||||
catch (HttpRequestException ex) { ret = ex.StatusCode == HttpStatusCode.NotFound ? "无" : ex.StatusCode.ToString() ?? "网络错误"; }
|
||||
catch (Exception) { }
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
|
||||
namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
internal static class CultureStorageExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// 添加本地化持久化策略服务
|
||||
/// </summary>
|
||||
/// <param name="services"></param>
|
||||
public static IServiceCollection AddCultureStorage(this IServiceCollection services)
|
||||
{
|
||||
services.TryAddSingleton<ICultureStorage, DefaultCultureStorage>();
|
||||
return services;
|
||||
}
|
||||
|
||||
internal class DefaultCultureStorage : ICultureStorage
|
||||
{
|
||||
public CultureStorageMode Mode { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,11 +21,11 @@
|
||||
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
|
||||
<link rel="apple-touch-icon" href="favicon.png">
|
||||
<base href="~/">
|
||||
<link rel="stylesheet" href="_content/BootstrapBlazor.Chart/css/bootstrap.blazor.chart.bundle.min.css">
|
||||
<link rel="stylesheet" href="_content/BootstrapBlazor.Markdown/css/bootstrap.blazor.markdown.min.css">
|
||||
<link rel="stylesheet" href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css">
|
||||
<link rel="stylesheet" href="_content/BootstrapBlazor.Shared/lib/highlight/vs.css">
|
||||
<link rel="stylesheet" href="_content/BootstrapBlazor.Shared/css/site.css">
|
||||
<link rel="stylesheet" href="_content/BootstrapBlazor/css/bootstrap.blazor.bundle.min.css" asp-append-version="true">
|
||||
<link rel="stylesheet" href="_content/BootstrapBlazor.Chart/css/bootstrap.blazor.chart.bundle.min.css" asp-append-version="true">
|
||||
<link rel="stylesheet" href="_content/BootstrapBlazor.Markdown/css/bootstrap.blazor.markdown.min.css" asp-append-version="true">
|
||||
<link rel="stylesheet" href="_content/BootstrapBlazor.Shared/lib/highlight/vs.css" asp-append-version="true">
|
||||
<link rel="stylesheet" href="_content/BootstrapBlazor.Shared/css/site.css" asp-append-version="true">
|
||||
<environment include="Staging,Production">
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
@@ -53,14 +53,15 @@
|
||||
<a href="" class="reload">Reload</a>
|
||||
<a class="dismiss"><i class="fa fa-times"></i></a>
|
||||
</div>
|
||||
|
||||
<script src="_framework/blazor.server.js"></script>
|
||||
<script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js"></script>
|
||||
<script src="_content/BootstrapBlazor.Chart/js/bootstrap.blazor.chart.bundle.min.js"></script>
|
||||
<script src="_content/BootstrapBlazor.TableExport/js/export.min.js"></script>
|
||||
<script src="_content/BootstrapBlazor.Markdown/js/bootstrap.blazor.markdown.min.js"></script>
|
||||
<script src="_content/BootstrapBlazor.Shared/lib/highlight/highlight.min.js"></script>
|
||||
<script src="_content/BootstrapBlazor.Shared/lib/summernote/summernote-zh-CN.min.js"></script>
|
||||
<script src="_content/BootstrapBlazor.Shared/js/common.js"></script>
|
||||
<div class="wwads-cn wwads-horizontal" data-id="72" style="max-width:350px"></div>
|
||||
<script src="_content/BootstrapBlazor/js/bootstrap.blazor.bundle.min.js" asp-append-version="true"></script>
|
||||
<script src="_content/BootstrapBlazor.Chart/js/bootstrap.blazor.chart.bundle.min.js" asp-append-version="true"></script>
|
||||
<script src="_content/BootstrapBlazor.TableExport/js/export.min.js" asp-append-version="true"></script>
|
||||
<script src="_content/BootstrapBlazor.Markdown/js/bootstrap.blazor.markdown.min.js" asp-append-version="true"></script>
|
||||
<script src="_content/BootstrapBlazor.Shared/lib/highlight/highlight.min.js" asp-append-version="true"></script>
|
||||
<script src="_content/BootstrapBlazor.Shared/lib/summernote/summernote-zh-CN.min.js" asp-append-version="true"></script>
|
||||
<script src="_content/BootstrapBlazor.Shared/js/common.js" asp-append-version="true"></script>
|
||||
<script src="_framework/blazor.server.js" asp-append-version="true"></script>
|
||||
<script src="https://wwads.cn/js/makemoney.js" type="text/javascript" async></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -11,6 +11,8 @@ using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace BootstrapBlazor.Server
|
||||
@@ -55,7 +57,6 @@ namespace BootstrapBlazor.Server
|
||||
services.AddControllers();
|
||||
services.AddRazorPages();
|
||||
services.AddServerSideBlazor();
|
||||
services.AddCultureStorage();
|
||||
|
||||
services.AddBlazorBackgroundTask();
|
||||
|
||||
@@ -64,7 +65,9 @@ namespace BootstrapBlazor.Server
|
||||
{
|
||||
// 统一设置 Toast 组件自动消失时间
|
||||
options.ToastDelay = 4000;
|
||||
options.Themes.Add(new System.Collections.Generic.KeyValuePair<string, string>("Ant Design (完善中)", "_content/BootstrapBlazor.Shared/css/ant.css"));
|
||||
options.Themes.AddRange(Configuration.GetSection("Themes")
|
||||
.GetChildren()
|
||||
.Select(c => new KeyValuePair<string, string>(c.Key, c.Value)));
|
||||
}, options =>
|
||||
{
|
||||
// 附加自己的 json 多语言文化资源文件 如 zh-TW.json
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"Microsoft.Hosting.Lifetime": "Information"
|
||||
}
|
||||
},
|
||||
"AllowOrigins": "http://localhost:5000",
|
||||
"WebsiteOptions": {
|
||||
"ServerUrl": "http://localhost:50853",
|
||||
"WasmUrl": "http://localhost:50855"
|
||||
|
||||
@@ -25,6 +25,12 @@
|
||||
"ServerUrl": "https://www.blazor.zone",
|
||||
"AdminUrl": "https://admin.blazor.zone",
|
||||
"ImageLibUrl": "https://imgs.blazor.zone",
|
||||
"WasmUrl": "https://wasm.blazor.zone"
|
||||
"WasmUrl": "https://wasm.blazor.zone",
|
||||
"TotalCount": 80
|
||||
},
|
||||
"Themes": {
|
||||
"Ant Design (完善中)": "_content/BootstrapBlazor.Shared/css/ant.css",
|
||||
"LayUI (完善中)": "_content/BootstrapBlazor.Shared/css/layui.css",
|
||||
"Bluma (完善中)": "_content/BootstrapBlazor.Shared/css/bluma.css"
|
||||
}
|
||||
}
|
||||
|
||||
BIN
src/BootstrapBlazor.Server/wwwroot/docs/imgs/Argo-Circle.png
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
src/BootstrapBlazor.Server/wwwroot/docs/imgs/Picture1.png
Normal file
|
After Width: | Height: | Size: 158 KiB |
BIN
src/BootstrapBlazor.Server/wwwroot/docs/imgs/Picture2.png
Normal file
|
After Width: | Height: | Size: 276 KiB |
BIN
src/BootstrapBlazor.Server/wwwroot/docs/imgs/Picture3.png
Normal file
|
After Width: | Height: | Size: 335 KiB |
BIN
src/BootstrapBlazor.Server/wwwroot/docs/imgs/Picture4.png
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
src/BootstrapBlazor.Server/wwwroot/docs/imgs/Picture5.png
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
src/BootstrapBlazor.Server/wwwroot/docs/imgs/Picture6.png
Normal file
|
After Width: | Height: | Size: 152 KiB |
BIN
src/BootstrapBlazor.Server/wwwroot/docs/imgs/Picture7.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
102
src/BootstrapBlazor.Server/wwwroot/docs/index.html
Normal file
@@ -0,0 +1,102 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
|
||||
<meta name="keywords" content="bootstrap,blazor,wasm,webassembly,UI,netcore,web,assembly">
|
||||
<meta name="author" content="argo (argo@163.com)">
|
||||
<title>Microsoft Docs Learn</title>
|
||||
<link rel="icon" href="https://devblogs.microsoft.com/visualstudio/wp-content/uploads/sites/4/2018/10/Microsoft-Favicon.png" sizes="32x32">
|
||||
<link rel="icon" href="https://devblogs.microsoft.com/visualstudio/wp-content/uploads/sites/4/2018/10/Microsoft-Favicon.png" sizes="192x192">
|
||||
<link rel="apple-touch-icon" href="https://devblogs.microsoft.com/visualstudio/wp-content/uploads/sites/4/2018/10/Microsoft-Favicon.png">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css" integrity="sha384-B0vP5xmATw1+K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2+l" crossorigin="anonymous">
|
||||
<script>
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?f147c9b2e3e0cc2b629c6390e5ffe377";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
|
||||
main {
|
||||
padding: 60px 16%;
|
||||
margin: 60px 0;
|
||||
box-shadow: 2px 2px 8px rgb(0 0 0 / 10%);
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
article h1 {
|
||||
text-align: center;
|
||||
font-size: 1.8rem;
|
||||
margin-bottom: 1.5rem;
|
||||
}
|
||||
|
||||
article h2 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-md">
|
||||
<main>
|
||||
<article>
|
||||
<h1>Docs & Learn Champion Best Practice Story</h1>
|
||||
<div class="text-center">
|
||||
<img src="imgs/Argo-Circle.png" style="width: 60px;" />
|
||||
</div>
|
||||
<div class="text-center" style="font-size:1.25rem;">
|
||||
<div class="mt-2">Guangpo Zhang</div>
|
||||
<div class="mt-2 mb-3" style="font-size:0.875rem; color: #616161;">April 27th, 2021</div>
|
||||
</div>
|
||||
<p>
|
||||
I am honored to be awarded as <a href="https://mvp.microsoft.com/en-us/PublicProfile/5004174" target="_blank">Microsoft MVP</a> on <b>March 1st, 2021</b>. Being MVP has always been my dream for a senior developer who has kept active in technical communities about 20 years.
|
||||
</p>
|
||||
<p>
|
||||
As soon as I joined the program, my CPM Christina Liang contacted with me immediately and arranged the onboarding meeting to introduce MVP Program and Docs & Learn Champion project. I thought Docs & Learn Champion was a fantastic project, which can help more people know MS Learn free learning platform, where they can find a systemtic knowledge and tool resource, so I registered this activity at once. Before I received my Creator ID, I have chose a dozen of Docs articles, vedios and learning modules from MS Docs and Learn website, prepared the original URLs to add my Creator ID later. Christina said I was as active and energetic as the generation of post 90s. Haha, it is my habit to take action fast. As a startup partner, I am very busy at work, so I treasure every minute in part time to build several personal technical websites, organize community learning groups and record learning videos, so when I think one thing is worth doing, I will take action fast to make it true, and more people can benefit from it soon.
|
||||
</p>
|
||||
<p>
|
||||
I was also astonished when Christina told me my score during March, with <b>3,287</b> total unique and <b>21,250</b> page views. Seeing so many visitors are interested in MS Learn content, I have momentum to contribute more on this thing. Maybe it is just because of my sharing, someone know Blazor and MS product and services, and will make use of it in their daily work and get achievement in the future. That’s what make us feel proud as a Microsoft MVP.
|
||||
</p>
|
||||
<img src="imgs/Picture1.png" class="w-100 py-3" />
|
||||
<p>Let me share my experience how I can attract 3,000+ visitors to see MS Docs and Learn website during one month.</p>
|
||||
<h2>Firstly</h2>
|
||||
<p>
|
||||
I add Docs links of Blazor official learning content at outsanding position on my persoanl website: <a href="https://www.blazor.zone" target="_blank">www.blazor.zone</a>, and I also made a popup box to introduce 8 important articles on Blazor, which beginner shall read them to have a general concept. Here is a small trick that I set up the popup box to cover some website content, most people would like to click them to have a look out of curiosity. Frankly speaking, they are very good learning content, and I highly recommend people to read them in my learning groups. The dashboard data says these 8 articles have got largest clicks, with each one over <b>3,200</b> views.
|
||||
</p>
|
||||
<img src="imgs/Picture2.png" class="w-100 py-3" />
|
||||
<img src="imgs/Picture3.png" class="w-100 py-3" />
|
||||
<h2>Secondly</h2>
|
||||
<p>I made two large-scale updates and advertisement for my website in March, which attracted new visitors that took <b>71.94%</b> of all visitors and attributed high clicks on my website. As shown in the screenshot below, you can see the visitors of my website in March was about 10,000 making <b>93,010</b> page views, so my Docs & Learn Champion unique visitors and page views are divided by my website data, we could find the transfer rates were <b>35.90%</b> and <b>22.8%</b> separately for unique visitors and page views. High percentage of my website visitors are interested in MS Learn content. </p>
|
||||
<img src="imgs/Picture7.png" class="w-100 py-3" />
|
||||
<img src="imgs/Picture4.png" class="w-100 py-3" />
|
||||
<h2>Thirdly</h2>
|
||||
<p>I made search engine optimization for some key words to get a satisfied result. Now, if people search words, such as blazor bootstrap ui in Chinese famous search engine – Baidu.com, they will be led to my website, and then have great probabilities to click MS Learn links I inserted there. </p>
|
||||
<img src="imgs/Picture5.png" class="w-100 py-3" />
|
||||
<h2>Fourthly</h2>
|
||||
<p>
|
||||
I organized Blazor community, and a number of learning groups. I would send MS Learn and Docs articles and modules into these community groups as learning material or answers to their questions. My hardworking administrators will also help me send these articles to group members. We are happy to receive members’ feedback that they felt the material is valuable and many of them sent screenshot to me showing they finished all modules.
|
||||
</p>
|
||||
<img src="imgs/Picture6.png" class="w-100 py-3" />
|
||||
<h2>Fifthly</h2>
|
||||
<p>I have several open-source projects, which will be updated every Thursday. I will send MS Learn content together with my open-source update news to the audience to share the popularity of update news, which usually attract over <b>2,000</b> views till next morning. </p>
|
||||
<h2>Sixthly</h2>
|
||||
<p>Taking a ride from official release. When .Net releases the preview version, people all actively discuss the new features, so I will post some blogs in the topic of these new features inserting MS Learn article links. For example, Microsoft recently released .Net preview 3 with hot reload feature, so I also post some blogs introducing blazor support hot reload and MS Learn courses. </p>
|
||||
<p>All in all, as a newcomer, there are a lot of things to be learned from experienced MVPs and CPMs. I hope my sharing can provide you with some reference. Through joining Docs & Learn Champion, I am excited to see so many developers are interested in Microsoft products and services, as well as this fantastic free MS Learn platform. It is a continuously updated storehouse of practical knowledge, and I hope more people would know it, use it and connect with each other to progress through my sharing. </p>
|
||||
</article>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -8,3 +8,5 @@
|
||||
</LayoutView>
|
||||
</NotFound>
|
||||
</Router>
|
||||
|
||||
<Title></Title>
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared
|
||||
{
|
||||
@@ -22,13 +24,13 @@ namespace BootstrapBlazor.Shared
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
protected override void OnAfterRender(bool firstRender)
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
base.OnAfterRender(firstRender);
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
if (firstRender && JSRuntime != null)
|
||||
if (firstRender && OperatingSystem.IsBrowser() && JSRuntime != null)
|
||||
{
|
||||
JSRuntime.InvokeVoidAsync("$.loading");
|
||||
await JSRuntime.InvokeVoidAsync("$.loading");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Version>5.0.0</Version>
|
||||
</PropertyGroup>
|
||||
@@ -18,9 +17,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BootstrapBlazor.Chart" Version="5.0.10" />
|
||||
<PackageReference Include="BootstrapBlazor.Markdown" Version="5.0.10" />
|
||||
<PackageReference Include="BootstrapBlazor.TableExport" Version="5.0.10" />
|
||||
<PackageReference Include="BootstrapBlazor.Chart" Version="5.0.18" />
|
||||
<PackageReference Include="BootstrapBlazor.Markdown" Version="5.0.18" />
|
||||
<PackageReference Include="BootstrapBlazor.TableExport" Version="5.0.18" />
|
||||
<PackageReference Include="System.Net.Http.Json" Version="5.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
private HttpClient Client { get; set; }
|
||||
|
||||
private bool IsWebAssembly { get; set; }
|
||||
|
||||
private string ServerUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
@@ -43,15 +41,13 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
/// </summary>
|
||||
/// <param name="client"></param>
|
||||
/// <param name="options"></param>
|
||||
/// <param name="storage"></param>
|
||||
public ExampleService(HttpClient client, IOptions<WebsiteOptions> options, ICultureStorage storage)
|
||||
public ExampleService(HttpClient client, IOptions<WebsiteOptions> options)
|
||||
{
|
||||
Client = client;
|
||||
Client.Timeout = TimeSpan.FromSeconds(5);
|
||||
Client.BaseAddress = new Uri(options.Value.RepositoryUrl);
|
||||
|
||||
ServerUrl = options.Value.ServerUrl;
|
||||
IsWebAssembly = storage.Mode == CultureStorageMode.LocalStorage;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -63,7 +59,7 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
var content = "";
|
||||
try
|
||||
{
|
||||
if (IsWebAssembly)
|
||||
if (OperatingSystem.IsBrowser())
|
||||
{
|
||||
Client.BaseAddress = new Uri($"{ServerUrl}/api/");
|
||||
content = await Client.GetStringAsync($"Code?fileName={CodeFile}");
|
||||
@@ -73,7 +69,8 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
content = await Client.GetStringAsync(CodeFile);
|
||||
}
|
||||
}
|
||||
catch (HttpRequestException) { content = "无"; }
|
||||
catch (HttpRequestException) { content = "网络错误"; }
|
||||
catch (TaskCanceledException) { }
|
||||
catch (Exception) { }
|
||||
return content;
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using BootstrapBlazor.Shared.Pages;
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using Microsoft.Extensions.DependencyInjection.Extensions;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
@@ -36,6 +35,13 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
{
|
||||
private List<TModel>? Items { get; set; }
|
||||
|
||||
private IStringLocalizer<TModel> Localizer { get; set; }
|
||||
|
||||
public TableDemoDataService(IStringLocalizer<TModel> localizer)
|
||||
{
|
||||
Localizer = localizer;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 查询操作方法
|
||||
/// </summary>
|
||||
@@ -44,7 +50,10 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
public override Task<QueryData<TModel>> QueryAsync(QueryPageOptions options)
|
||||
{
|
||||
// 此处代码实战中不可用,仅仅为演示而写
|
||||
if (Items == null || Items.Count == 0) Items = TablesBase.GenerateItems().Cast<TModel>().ToList();
|
||||
if (Items == null || Items.Count == 0)
|
||||
{
|
||||
Items = Foo.GenerateFoo((IStringLocalizer<Foo>)Localizer).Cast<TModel>().ToList();
|
||||
}
|
||||
|
||||
var total = Items.Count;
|
||||
|
||||
@@ -108,7 +117,11 @@ namespace Microsoft.Extensions.DependencyInjection
|
||||
|
||||
public override Task<bool> DeleteAsync(IEnumerable<TModel> models)
|
||||
{
|
||||
foreach (var model in models) Items?.Remove(model);
|
||||
foreach (var model in models)
|
||||
{
|
||||
Items?.Remove(model);
|
||||
}
|
||||
|
||||
return base.DeleteAsync(models);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,6 +92,11 @@ namespace BootstrapBlazor.Shared
|
||||
/// </summary>
|
||||
public string CurrentTheme { get; set; } = "";
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 组件总数
|
||||
/// </summary>
|
||||
public int TotalCount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 构造函数
|
||||
/// </summary>
|
||||
|
||||
@@ -1,103 +0,0 @@
|
||||
{
|
||||
"BootstrapBlazor.Shared.Pages.Components.Block": {
|
||||
"Title": "",
|
||||
"SubTitle": "Demo"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.AttributeTable": {
|
||||
"Title": "Attributes"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.MethodTable": {
|
||||
"Title": "Methods"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.AttributeItem": {
|
||||
"Name": "Parameter",
|
||||
"Description": "Description",
|
||||
"Type": "Type",
|
||||
"ValueList": "ValueList",
|
||||
"DefaultValue": "DefaultValue"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.EventItem": {
|
||||
"Name": "Parameter",
|
||||
"Description": "Description",
|
||||
"Type": "Type"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.MethodItem": {
|
||||
"Title": "Methods",
|
||||
"Name": "Parameter",
|
||||
"Description": "Description",
|
||||
"Type": "Type",
|
||||
"Parameters": "Parameters",
|
||||
"ReturnValue": "ReturnValue"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Shared.ComponentLayout": {
|
||||
"Title": "Enterprise-level component library based on Bootstrap and Blazor",
|
||||
"Example": "Example",
|
||||
"Video": "Video"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Alerts": {
|
||||
"Title": "Alert",
|
||||
"SubTitle": "Displays important alert messages.",
|
||||
"BaseUsageText": "Basic usage",
|
||||
"IntroText1": "Alert components are non-overlay elements in the page that does not disappear automatically.",
|
||||
"AlertPrimaryText": "A simple primary alert—check it out!",
|
||||
"AlertSecondaryText": "A simple secondary alert—check it out!",
|
||||
"AlertSuccessText": "A simple success alert—check it out!",
|
||||
"AlertDangerText": "A simple danger alert—check it out!",
|
||||
"AlertWarningText": "A simple warning alert—check it out!",
|
||||
"AlertInfoText": "A simple info alert—check it out!",
|
||||
"AlertDarkText": "A simple dark alert—check it out!",
|
||||
"CloseButtonUsageText": "Close button",
|
||||
"IntroText2": "Customize the close button as texts or other symbols.",
|
||||
"WithIconUsageText": "With Icon",
|
||||
"IntroText3": "Displaying an icon improves readability.",
|
||||
"ShowBarUsageText": "With Bar",
|
||||
"IntroText4": "Show <code>Tip</code>"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.QRCodes": {
|
||||
"Title": "QRCode",
|
||||
"SubTitle": "Generate QR code",
|
||||
"BaseUsageText": "Basic usage",
|
||||
"IntroText1": "Click the Generate button to generate a <code>QRCode</code>",
|
||||
"SuccessText": "QR code generated successfully",
|
||||
"CallbackDescription": "Call back after QR code generation"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Anchors": {
|
||||
"Title": "Anchor",
|
||||
"SubTitle": "Hyperlinks to scroll on one page.",
|
||||
"BaseUsageText": "Basic usage",
|
||||
"IntroText1": "For displaying anchor hyperlinks on page and jumping between them.",
|
||||
"IntroText2": "Click <code>Anchor</code> item try it",
|
||||
"ContentText1": "<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p><p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p><p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p><p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p><p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.Foo": {
|
||||
"Name": "Name",
|
||||
"DateTime": "DateTime",
|
||||
"Address": "Address",
|
||||
"Count": "Count",
|
||||
"Complete": "Complete",
|
||||
"Education": "Education",
|
||||
"Hobby": "Hobby",
|
||||
"Name.Required": "{0} is required.",
|
||||
"Address.Required": "{0} is required.",
|
||||
"Education.Required": "{0} is required.",
|
||||
"Hobby.Required": "{0} is required.",
|
||||
"Name.PlaceHolder": "required",
|
||||
"Hobbys": "Swimming,Climb,Shoot,Chess",
|
||||
"Foo.Name": "Zhangsan {0}",
|
||||
"Foo.Address": "Lane {0} of Jinshajiang Road, Putuo District, Shanghai",
|
||||
"Foo.Address2": "Earth, China, Lane {0} of Jinshajiang Road, Putuo District, Shanghai. Here is an example of super long cell",
|
||||
"Foo.BindValue": "BindValue"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.EnumEducation": {
|
||||
"PlaceHolder": "Click to select ...",
|
||||
"Primary": "Primary",
|
||||
"Middel": "Middel"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Inputs": {
|
||||
"PlaceHolder": "please input ..."
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.ThemeChooser": {
|
||||
"Title": "Click to choose theme",
|
||||
"HeaderText": "Themes"
|
||||
}
|
||||
}
|
||||
284
src/BootstrapBlazor.Shared/Locales/en.json
Normal file
@@ -0,0 +1,284 @@
|
||||
{
|
||||
"BootstrapBlazor.Shared.App": {
|
||||
"Title": "Bootstrap of Blazor"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.Block": {
|
||||
"Title": "",
|
||||
"SubTitle": "Demo"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.AttributeTable": {
|
||||
"Title": "Attributes"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.MethodTable": {
|
||||
"Title": "Methods"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.AttributeItem": {
|
||||
"Name": "Parameter",
|
||||
"Description": "Description",
|
||||
"Type": "Type",
|
||||
"ValueList": "ValueList",
|
||||
"DefaultValue": "DefaultValue"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.EventItem": {
|
||||
"Name": "Parameter",
|
||||
"Description": "Description",
|
||||
"Type": "Type"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.MethodItem": {
|
||||
"Title": "Methods",
|
||||
"Name": "Parameter",
|
||||
"Description": "Description",
|
||||
"Type": "Type",
|
||||
"Parameters": "Parameters",
|
||||
"ReturnValue": "ReturnValue"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Shared.ComponentLayout": {
|
||||
"Title": "Enterprise-level component library based on Bootstrap and Blazor",
|
||||
"Example": "Example",
|
||||
"Video": "Video"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Alerts": {
|
||||
"Title": "Alert",
|
||||
"SubTitle": "Displays important alert messages.",
|
||||
"BaseUsageText": "Basic usage",
|
||||
"IntroText1": "Alert components are non-overlay elements in the page that does not disappear automatically.",
|
||||
"AlertPrimaryText": "A simple primary alert—check it out!",
|
||||
"AlertSecondaryText": "A simple secondary alert—check it out!",
|
||||
"AlertSuccessText": "A simple success alert—check it out!",
|
||||
"AlertDangerText": "A simple danger alert—check it out!",
|
||||
"AlertWarningText": "A simple warning alert—check it out!",
|
||||
"AlertInfoText": "A simple info alert—check it out!",
|
||||
"AlertDarkText": "A simple dark alert—check it out!",
|
||||
"CloseButtonUsageText": "Close button",
|
||||
"IntroText2": "Customize the close button as texts or other symbols.",
|
||||
"WithIconUsageText": "With Icon",
|
||||
"IntroText3": "Displaying an icon improves readability.",
|
||||
"ShowBarUsageText": "With Bar",
|
||||
"IntroText4": "Show <code>Tip</code>"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Selects": {
|
||||
"PlaceHolder": "Not Select"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.QRCodes": {
|
||||
"Title": "QRCode",
|
||||
"SubTitle": "Generate QR code",
|
||||
"BaseUsageText": "Basic usage",
|
||||
"IntroText1": "Click the Generate button to generate a <code>QRCode</code>",
|
||||
"SuccessText": "QR code generated successfully",
|
||||
"CallbackDescription": "Call back after QR code generation"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Anchors": {
|
||||
"Title": "Anchor",
|
||||
"SubTitle": "Hyperlinks to scroll on one page.",
|
||||
"BaseUsageText": "Basic usage",
|
||||
"IntroText1": "For displaying anchor hyperlinks on page and jumping between them.",
|
||||
"IntroText2": "Click <code>Anchor</code> item try it",
|
||||
"ContentText1": "<p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p><p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p><p>Aenean lacinia bibendum nulla sed consectetur. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Donec sed odio dui. Donec ullamcorper nulla non metus auctor fringilla.</p><p>Cras mattis consectetur purus sit amet fermentum. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.</p><p>Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Vivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor.</p>"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.Foo": {
|
||||
"Name": "Name",
|
||||
"DateTime": "DateTime",
|
||||
"Address": "Address",
|
||||
"Count": "Count",
|
||||
"Complete": "Complete",
|
||||
"Education": "Education",
|
||||
"Hobby": "Hobby",
|
||||
"Name.Required": "{0} is required.",
|
||||
"Address.Required": "{0} is required.",
|
||||
"Education.Required": "{0} is required.",
|
||||
"Hobby.Required": "{0} is required.",
|
||||
"Name.PlaceHolder": "required",
|
||||
"Hobbys": "Swimming,Climb,Shoot,Chess",
|
||||
"Foo.Name": "Zhangsan {0}",
|
||||
"Foo.Address": "Lane {0} of Jinshajiang Road, Putuo District, Shanghai",
|
||||
"Foo.Address2": "Earth, China, Lane {0} of Jinshajiang Road, Putuo District, Shanghai. Here is an example of super long cell",
|
||||
"Foo.BindValue": "BindValue"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.ValidateForms.ComplexFoo": {
|
||||
"Name": "Name",
|
||||
"Name.Required": "{0} is required."
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.ValidateForms.Dummy2": {
|
||||
"Name": "Name",
|
||||
"Name.Required": "Dummy2 {0} is required"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.EnumEducation": {
|
||||
"PlaceHolder": "Click to select ...",
|
||||
"Primary": "Primary",
|
||||
"Middel": "Middel"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Inputs": {
|
||||
"PlaceHolder": "please input ..."
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.ThemeChooser": {
|
||||
"Title": "Click to choose theme",
|
||||
"HeaderText": "Themes"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Uploads.Person": {
|
||||
"Name": "Name",
|
||||
"Name.Required": "{0} is required",
|
||||
"Picture": "File",
|
||||
"Picture.Required": "{0} is required"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.CultureChooser": {
|
||||
"Label": "Language:"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Shared.BaseLayout": {
|
||||
"DownloadText": "Download",
|
||||
"HomeText": "Home",
|
||||
"IntroductionText": "Documents",
|
||||
"ComponentsText": "Components",
|
||||
"FlowText": "Workflow",
|
||||
"InstallAppText": "Install PWA App",
|
||||
"InstallText": "Install",
|
||||
"CancelText": "Cancel"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Shared.NavMenu": {
|
||||
"GetStarted": "GETTINGSTARTED",
|
||||
"Introduction": "Introduction",
|
||||
"Install": "Install",
|
||||
"ProjectTemplate": "Template",
|
||||
"Globalization": "Globalization",
|
||||
"Localization": "Localization",
|
||||
"ServerBlazor": "Server-side Blazor",
|
||||
"ClientBlazor": "Client-side Blazor",
|
||||
"Labels": "Labels",
|
||||
"LayoutPage": "LayoutPage",
|
||||
"Components": "COMPONENTS",
|
||||
"LayoutComponents": "LAYOUTS",
|
||||
"Divider": "Divider",
|
||||
"Layout": "Layout",
|
||||
"Footer": "Footer",
|
||||
"Row": "Row",
|
||||
"Scroll": "Scroll",
|
||||
"Skeleton": "Skeleton",
|
||||
"Split": "Split",
|
||||
"NavigationComponents": "NAVIGATIONS",
|
||||
"Anchor": "Anchor",
|
||||
"Breadcrumb": "Breadcrumb",
|
||||
"Dropdown": "Dropdown",
|
||||
"GoTop": "GoTop",
|
||||
"Menu": "Menu",
|
||||
"Nav": "Nav",
|
||||
"Pagination": "Pagination",
|
||||
"Steps": "Steps",
|
||||
"Tab": "Tab",
|
||||
"NotificationComponents": "NOTIFICATIONS",
|
||||
"Alert": "Alert",
|
||||
"Console": "Console",
|
||||
"Dialog": "Dialog",
|
||||
"Drawer": "Drawer",
|
||||
"EditDialog": "EditDialog",
|
||||
"Message": "Message",
|
||||
"Modal": "Modal",
|
||||
"Light": "Light",
|
||||
"Popconfirm": "Popconfirm",
|
||||
"Progress": "Progress",
|
||||
"SearchDialog": "SearchDialog",
|
||||
"Spinner": "Spinner",
|
||||
"SweetAlert": "SweetAlert",
|
||||
"Timer": "Timer",
|
||||
"Toast": "Toast",
|
||||
"FormsComponents": "FORMS",
|
||||
"AutoComplete": "AutoComplete",
|
||||
"Button": "Button",
|
||||
"Cascader": "Cascader",
|
||||
"Checkbox": "Checkbox",
|
||||
"CheckboxList": "CheckboxList",
|
||||
"ColorPicker": "ColorPicker",
|
||||
"DateTimePicker": "DateTimePicker",
|
||||
"DateTimeRange": "DateTimeRange",
|
||||
"Editor": "Editor",
|
||||
"EditorForm": "EditorForm",
|
||||
"Input": "Input",
|
||||
"InputNumber": "InputNumber",
|
||||
"Markdown": "Markdown",
|
||||
"MultiSelect": "MultiSelect",
|
||||
"Radio": "Radio",
|
||||
"Rate": "Rate",
|
||||
"Select": "Select",
|
||||
"Slider": "Slider",
|
||||
"Switch": "Switch",
|
||||
"Textarea": "Textarea",
|
||||
"Toggle": "Toggle",
|
||||
"Transfer": "Transfer",
|
||||
"Upload": "Upload",
|
||||
"ValidateForm": "ValidateForm",
|
||||
"DataComponents": "DATAS",
|
||||
"Avatar": "Avatar",
|
||||
"Badge": "Badge",
|
||||
"BarcodeReader": "BarcodeReader",
|
||||
"Card": "Card",
|
||||
"Calendar": "Calendar",
|
||||
"Camera": "Camera",
|
||||
"Captcha": "Captcha",
|
||||
"Carousel": "Carousel",
|
||||
"Chart": "Chart",
|
||||
"Circle": "Circle",
|
||||
"Collapse": "Collapse",
|
||||
"Display": "Display",
|
||||
"DropdownWidget": "DropdownWidget",
|
||||
"GroupBox": "GroupBox",
|
||||
"HandwrittenPage": "HandwrittenPage",
|
||||
"ListView": "ListView",
|
||||
"Popover": "Popover",
|
||||
"QRCode": "QRCode",
|
||||
"Search": "Search",
|
||||
"Tag": "Tag",
|
||||
"Timeline": "Timeline",
|
||||
"Title": "Title",
|
||||
"Download": "Download",
|
||||
"Tooltip": "Tooltip",
|
||||
"Tree": "Tree",
|
||||
"Table": "Table",
|
||||
"TableBase": "Base",
|
||||
"TableRow": "Row",
|
||||
"TableColumn": "Column",
|
||||
"TableDetail": "Detail",
|
||||
"TableSearch": "Search",
|
||||
"TableFilter": "Sort/Filter",
|
||||
"TableFixHeader": "FixHeader",
|
||||
"TableHeaderGroup": "HeaderGroup",
|
||||
"TableFixColumn": "FixColumn",
|
||||
"TablePage": "Pagination",
|
||||
"TableToolbar": "Toolbar",
|
||||
"TableEdit": "Edit",
|
||||
"TableExport": "Export",
|
||||
"TableSelection": "Selection",
|
||||
"TableAutoRefresh": "AutoRefresh",
|
||||
"TableFooter": "Footer",
|
||||
"TableDialog": "Table-Dialog",
|
||||
"TableWrap": "Wrap",
|
||||
"TableTree": "Table-Tree",
|
||||
"TableLaoding": "Table-Loading",
|
||||
"MenuAccordion": "Accordion",
|
||||
"MenuExpandAll": "Expand"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Menus": {
|
||||
"System": "System",
|
||||
"Website": "Website",
|
||||
"Task": "Task",
|
||||
"Authorize": "Authorize",
|
||||
"User": "User",
|
||||
"Menu": "Menu",
|
||||
"Role": "Role",
|
||||
"Log": "Log",
|
||||
"Access": "Access",
|
||||
"Login": "Login",
|
||||
"Operation": "Operation",
|
||||
"Nav1": "Menu 1",
|
||||
"Nav2": "Menu 2",
|
||||
"Nav3": "Menu 3",
|
||||
"SubMenu1": "Sub Menu 1",
|
||||
"SubMenu2": "Sub Menu 2",
|
||||
"SubMenu3": "Sub Menu 3",
|
||||
"SubMenu11": "Sub Menu 11",
|
||||
"SubMenu12": "Sub Menu 12",
|
||||
"SubMenu21": "Sub Menu 21",
|
||||
"SubMenu22": "Sub Menu 22",
|
||||
"SubMenu31": "Sub Menu 31",
|
||||
"SubMenu32": "Sub Menu 32",
|
||||
"SubMenu41": "Sub Menu 41",
|
||||
"SubMenu42": "Sub Menu 42"
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
{
|
||||
"BootstrapBlazor.Shared.Pages.Components.Block": {
|
||||
"Title": "未设置",
|
||||
"SubTitle": "示例"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.AttributeTable": {
|
||||
"Title": "Attributes 属性"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.MethodTable": {
|
||||
"Title": "Methods 方法"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.AttributeItem": {
|
||||
"Name": "参数",
|
||||
"Description": "说明",
|
||||
"Type": "类型",
|
||||
"ValueList": "可选值",
|
||||
"DefaultValue": "默认值"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.EventItem": {
|
||||
"Name": "参数",
|
||||
"Description": "说明",
|
||||
"Type": "类型"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.MethodItem": {
|
||||
"Title": "Methods 方法",
|
||||
"Name": "参数",
|
||||
"Description": "说明",
|
||||
"Type": "类型",
|
||||
"Parameters": "参数",
|
||||
"ReturnValue": "返回值"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Shared.ComponentLayout": {
|
||||
"Title": "基于 Bootstrap 和 Blazor 的企业级组件库",
|
||||
"Example": "示例",
|
||||
"Video": "相关视频"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Alerts": {
|
||||
"Title": "Alert 警告",
|
||||
"SubTitle": "用于页面中展示重要的提示信息。",
|
||||
"BaseUsageText": "基本用法",
|
||||
"IntroText1": "页面中的非浮层元素,不会自动消失。",
|
||||
"AlertPrimaryText": "主要的警告框",
|
||||
"AlertSecondaryText": "次要的警告框",
|
||||
"AlertSuccessText": "成功的警告框",
|
||||
"AlertDangerText": "危险的警告框",
|
||||
"AlertWarningText": "警告的警告框",
|
||||
"AlertInfoText": "信息的警告框",
|
||||
"AlertDarkText": "黑暗的警告框",
|
||||
"CloseButtonUsageText": "关闭按钮",
|
||||
"IntroText2": "提供关闭按钮的警告框",
|
||||
"WithIconUsageText": "带 Icon",
|
||||
"IntroText3": "表示某种状态时提升可读性。",
|
||||
"ShowBarUsageText": "显示左侧 Bar",
|
||||
"IntroText4": "作为 <code>Tip</code> 使用"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.QRCodes": {
|
||||
"Title": "QRCode 二维码",
|
||||
"SubTitle": "用于二维码生成",
|
||||
"BaseUsageText": "基本用法",
|
||||
"IntroText1": "点击生成按钮,生成特定的 <code>QRCode</code>",
|
||||
"SuccessText": "二维码生成成功",
|
||||
"CallbackDescription": "二维码生成后回调委托"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Anchors": {
|
||||
"Title": "Anchor 锚点",
|
||||
"SubTitle": "用于跳转到页面指定位置",
|
||||
"BaseUsageText": "基本用法",
|
||||
"IntroText1": "需要展现当前页面上可供跳转的锚点链接,以及快速在锚点之间跳转",
|
||||
"IntroText2": "点击下面 <code>Anchor</code> 项目,页面滚动到相对应的章节",
|
||||
"ContentText1": "<p>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</p><p>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</p><p>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</p><p>简化流程:设计简洁直观的操作流程;</p><p>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</p><p>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</p>"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.Foo": {
|
||||
"Name": "姓名",
|
||||
"DateTime": "日期",
|
||||
"Address": "地址",
|
||||
"Count": "数量",
|
||||
"Complete": "是/否",
|
||||
"Education": "学历",
|
||||
"Hobby": "爱好",
|
||||
"Name.Required": "{0}是必填项",
|
||||
"Address.Required": "{0}是必填项",
|
||||
"Education.Required": "{0}是必选项",
|
||||
"Hobby.Required": "请选择一种{0}",
|
||||
"Name.PlaceHolder": "不可为空",
|
||||
"Hobbys": "游泳,登山,打球,下棋",
|
||||
"Foo.Name": "张三 {0}",
|
||||
"Foo.Address": "上海市普陀区金沙江路 {0} 弄",
|
||||
"Foo.Address2": "地球、中国、上海市普陀区金沙江路 {0} 弄 这里是超长单元格示例",
|
||||
"Foo.BindValue": "绑定值"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.EnumEducation": {
|
||||
"PlaceHolder": "请选择 ...",
|
||||
"Primary": "小学",
|
||||
"Middel": "中学"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Inputs": {
|
||||
"PlaceHolder": "请输入 ..."
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.ThemeChooser": {
|
||||
"Title": "点击切换主题",
|
||||
"HeaderText": "请选择主题"
|
||||
}
|
||||
}
|
||||
284
src/BootstrapBlazor.Shared/Locales/zh.json
Normal file
@@ -0,0 +1,284 @@
|
||||
{
|
||||
"BootstrapBlazor.Shared.App": {
|
||||
"Title": "Bootstrap Blazor - 企业级 UI 组件库"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.Block": {
|
||||
"Title": "未设置",
|
||||
"SubTitle": "示例"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.AttributeTable": {
|
||||
"Title": "Attributes 属性"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.MethodTable": {
|
||||
"Title": "Methods 方法"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.AttributeItem": {
|
||||
"Name": "参数",
|
||||
"Description": "说明",
|
||||
"Type": "类型",
|
||||
"ValueList": "可选值",
|
||||
"DefaultValue": "默认值"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.EventItem": {
|
||||
"Name": "参数",
|
||||
"Description": "说明",
|
||||
"Type": "类型"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Common.MethodItem": {
|
||||
"Title": "Methods 方法",
|
||||
"Name": "参数",
|
||||
"Description": "说明",
|
||||
"Type": "类型",
|
||||
"Parameters": "参数",
|
||||
"ReturnValue": "返回值"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Shared.ComponentLayout": {
|
||||
"Title": "基于 Bootstrap 和 Blazor 的企业级组件库",
|
||||
"Example": "示例",
|
||||
"Video": "相关视频"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Alerts": {
|
||||
"Title": "Alert 警告",
|
||||
"SubTitle": "用于页面中展示重要的提示信息。",
|
||||
"BaseUsageText": "基本用法",
|
||||
"IntroText1": "页面中的非浮层元素,不会自动消失。",
|
||||
"AlertPrimaryText": "主要的警告框",
|
||||
"AlertSecondaryText": "次要的警告框",
|
||||
"AlertSuccessText": "成功的警告框",
|
||||
"AlertDangerText": "危险的警告框",
|
||||
"AlertWarningText": "警告的警告框",
|
||||
"AlertInfoText": "信息的警告框",
|
||||
"AlertDarkText": "黑暗的警告框",
|
||||
"CloseButtonUsageText": "关闭按钮",
|
||||
"IntroText2": "提供关闭按钮的警告框",
|
||||
"WithIconUsageText": "带 Icon",
|
||||
"IntroText3": "表示某种状态时提升可读性。",
|
||||
"ShowBarUsageText": "显示左侧 Bar",
|
||||
"IntroText4": "作为 <code>Tip</code> 使用"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Selects": {
|
||||
"PlaceHolder": "未选择"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.QRCodes": {
|
||||
"Title": "QRCode 二维码",
|
||||
"SubTitle": "用于二维码生成",
|
||||
"BaseUsageText": "基本用法",
|
||||
"IntroText1": "点击生成按钮,生成特定的 <code>QRCode</code>",
|
||||
"SuccessText": "二维码生成成功",
|
||||
"CallbackDescription": "二维码生成后回调委托"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Anchors": {
|
||||
"Title": "Anchor 锚点",
|
||||
"SubTitle": "用于跳转到页面指定位置",
|
||||
"BaseUsageText": "基本用法",
|
||||
"IntroText1": "需要展现当前页面上可供跳转的锚点链接,以及快速在锚点之间跳转",
|
||||
"IntroText2": "点击下面 <code>Anchor</code> 项目,页面滚动到相对应的章节",
|
||||
"ContentText1": "<p>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</p><p>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</p><p>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</p><p>简化流程:设计简洁直观的操作流程;</p><p>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</p><p>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</p>"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.Foo": {
|
||||
"Name": "姓名",
|
||||
"DateTime": "日期",
|
||||
"Address": "地址",
|
||||
"Count": "数量",
|
||||
"Complete": "是/否",
|
||||
"Education": "学历",
|
||||
"Hobby": "爱好",
|
||||
"Name.Required": "{0}是必填项",
|
||||
"Address.Required": "{0}是必填项",
|
||||
"Education.Required": "{0}是必选项",
|
||||
"Hobby.Required": "请选择一种{0}",
|
||||
"Name.PlaceHolder": "不可为空",
|
||||
"Hobbys": "游泳,登山,打球,下棋",
|
||||
"Foo.Name": "张三 {0}",
|
||||
"Foo.Address": "上海市普陀区金沙江路 {0} 弄",
|
||||
"Foo.Address2": "地球、中国、上海市普陀区金沙江路 {0} 弄 这里是超长单元格示例",
|
||||
"Foo.BindValue": "绑定值"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.ValidateForms.ComplexFoo": {
|
||||
"Name": "姓名",
|
||||
"Name.Required": "{0} 值是必填项"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.ValidateForms.Dummy2": {
|
||||
"Name": "姓名",
|
||||
"Name.Required": "Dummy2 {0} 值是必填项"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.EnumEducation": {
|
||||
"PlaceHolder": "请选择 ...",
|
||||
"Primary": "小学",
|
||||
"Middel": "中学"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Inputs": {
|
||||
"PlaceHolder": "请输入 ..."
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.ThemeChooser": {
|
||||
"Title": "点击切换主题",
|
||||
"HeaderText": "请选择主题"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Uploads.Person": {
|
||||
"Name": "姓名",
|
||||
"Name.Required": "{0}不能为空",
|
||||
"Picture": "上传文件",
|
||||
"Picture.Required": "上传文件不能为空"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Components.CultureChooser": {
|
||||
"Label": "语言:"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Shared.BaseLayout": {
|
||||
"DownloadText": "Download",
|
||||
"HomeText": "首页",
|
||||
"IntroductionText": "文档",
|
||||
"ComponentsText": "组件",
|
||||
"FlowText": "工作流",
|
||||
"InstallAppText": "安装小程序",
|
||||
"InstallText": "安装",
|
||||
"CancelText": "取消"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Shared.NavMenu": {
|
||||
"GetStarted": "快速上手",
|
||||
"Introduction": "简介",
|
||||
"Install": "类库安装",
|
||||
"ProjectTemplate": "项目模板",
|
||||
"Globalization": "全球化",
|
||||
"Localization": "本地化",
|
||||
"ServerBlazor": "服务器端模式",
|
||||
"ClientBlazor": "客户端模式",
|
||||
"Labels": "表单标签",
|
||||
"LayoutPage": "后台模拟器",
|
||||
"Components": "组件总览",
|
||||
"LayoutComponents": "布局组件",
|
||||
"Divider": "分割线 Divider",
|
||||
"Layout": "布局组件 Layout",
|
||||
"Footer": "页脚组件 Footer",
|
||||
"Row": "行组件 Row",
|
||||
"Scroll": "滚动条 Scroll",
|
||||
"Skeleton": "骨架屏 Skeleton",
|
||||
"Split": "分割面板 Split",
|
||||
"NavigationComponents": "导航组件",
|
||||
"Anchor": "锚点 Anchor",
|
||||
"Breadcrumb": "面包屑 Breadcrumb",
|
||||
"Dropdown": "下拉菜单 Dropdown",
|
||||
"GoTop": "跳转组件 GoTop",
|
||||
"Menu": "菜单 Menu",
|
||||
"Nav": "导航栏 Nav",
|
||||
"Pagination": "分页 Pagination",
|
||||
"Steps": "步骤条 Steps",
|
||||
"Tab": "标签页 Tab",
|
||||
"NotificationComponents": "通知组件",
|
||||
"Alert": "警告框 Alert",
|
||||
"Console": "控制台 Console",
|
||||
"Dialog": "对话框 Dialog",
|
||||
"Drawer": "抽屉 Drawer",
|
||||
"EditDialog": "编辑弹窗 EditDialog",
|
||||
"Message": "消息框 Message",
|
||||
"Modal": "模态框 Modal",
|
||||
"Light": "指示灯 Light",
|
||||
"Popconfirm": "确认框 Popconfirm",
|
||||
"Progress": "进度条 Progress",
|
||||
"SearchDialog": "搜索弹窗 SearchDialog",
|
||||
"Spinner": "旋转图标 Spinner",
|
||||
"SweetAlert": "模态弹框 SweetAlert",
|
||||
"Timer": "计时器 Timer",
|
||||
"Toast": "轻量弹窗 Toast",
|
||||
"FormsComponents": "表单组件",
|
||||
"AutoComplete": "自动完成 AutoComplete",
|
||||
"Button": "按钮 Button",
|
||||
"Cascader": "级联选择 Cascader",
|
||||
"Checkbox": "多选框 Checkbox",
|
||||
"CheckboxList": "多选框组 CheckboxList",
|
||||
"ColorPicker": "颜色拾取器 ColorPicker",
|
||||
"DateTimePicker": "时间框 DateTimePicker",
|
||||
"DateTimeRange": "时间范围框 DateTimeRange",
|
||||
"Editor": "富文本框 Editor",
|
||||
"EditorForm": "表单编辑框 EditorForm",
|
||||
"Input": "输入框 Input",
|
||||
"InputNumber": "数字框 InputNumber",
|
||||
"Markdown": "富文本框 Markdown",
|
||||
"MultiSelect": "多项选择器 MultiSelect",
|
||||
"Radio": "单选框 Radio",
|
||||
"Rate": "评分 Rate",
|
||||
"Select": "选择器 Select",
|
||||
"Slider": "滑块 Slider",
|
||||
"Switch": "开关 Switch",
|
||||
"Textarea": "多行文本框 Textarea",
|
||||
"Toggle": "开关 Toggle",
|
||||
"Transfer": "穿梭框 Transfer",
|
||||
"Upload": "上传组件 Upload",
|
||||
"ValidateForm": "验证表单 ValidateForm",
|
||||
"DataComponents": "数据组件",
|
||||
"Avatar": "头像框 Avatar",
|
||||
"Badge": "徽章 Badge",
|
||||
"BarcodeReader": "条码扫描 BarcodeReader",
|
||||
"Card": "卡片 Card",
|
||||
"Calendar": "日历框 Calendar",
|
||||
"Camera": "摄像头 Camera",
|
||||
"Captcha": "验证码 Captcha",
|
||||
"Carousel": "走马灯 Carousel",
|
||||
"Chart": "图表 Chart",
|
||||
"Circle": "进度环 Circle",
|
||||
"Collapse": "折叠 Collapse",
|
||||
"Display": "数据显示 Display",
|
||||
"DropdownWidget": "挂件 DropdownWidget",
|
||||
"GroupBox": "集合 GroupBox",
|
||||
"HandwrittenPage": "手写组件 HandwrittenPage",
|
||||
"ListView": "列表组件 ListView",
|
||||
"Popover": "弹出窗 Popover",
|
||||
"QRCode": "二维码 QRCode",
|
||||
"Search": "搜索框 Search",
|
||||
"Tag": "标签 Tag",
|
||||
"Timeline": "时间线 Timeline",
|
||||
"Title": "网站标题 Title",
|
||||
"Download": "文件下载 Download",
|
||||
"Tooltip": "工具条 Tooltip",
|
||||
"Tree": "树形组件 Tree",
|
||||
"Table": "表格组件",
|
||||
"TableBase": "基本功能",
|
||||
"TableRow": "行设置",
|
||||
"TableColumn": "列设置",
|
||||
"TableDetail": "明细行",
|
||||
"TableSearch": "搜索功能",
|
||||
"TableFilter": "筛选和排序",
|
||||
"TableFixHeader": "固定表头",
|
||||
"TableHeaderGroup": "表头分组",
|
||||
"TableFixColumn": "固定列",
|
||||
"TablePage": "分页功能",
|
||||
"TableToolbar": "工具栏",
|
||||
"TableEdit": "表单维护",
|
||||
"TableExport": "导出功能",
|
||||
"TableSelection": "行选中",
|
||||
"TableAutoRefresh": "自动刷新",
|
||||
"TableFooter": "统计合并",
|
||||
"TableDialog": "弹窗联动",
|
||||
"TableWrap": "折行演示",
|
||||
"TableTree": "树形数据",
|
||||
"TableLaoding": "数据加载",
|
||||
"MenuAccordion": "手风琴效果",
|
||||
"MenuExpandAll": "全部展开"
|
||||
},
|
||||
"BootstrapBlazor.Shared.Pages.Menus": {
|
||||
"System": "系统设置",
|
||||
"Website": "网站设置",
|
||||
"Task": "任务设置",
|
||||
"Authorize": "权限设置",
|
||||
"User": "用户设置",
|
||||
"Menu": "菜单设置",
|
||||
"Role": "角色设置",
|
||||
"Log": "日志设置",
|
||||
"Access": "访问日志",
|
||||
"Login": "登录日志",
|
||||
"Operation": "操作日志",
|
||||
"Menu1": "菜单一",
|
||||
"Menu2": "菜单二",
|
||||
"Menu3": "菜单三",
|
||||
"SubMenu1": "子菜单 1",
|
||||
"SubMenu2": "子菜单 2",
|
||||
"SubMenu3": "子菜单 3",
|
||||
"SubMenu11": "孙菜单 11",
|
||||
"SubMenu12": "孙菜单 12",
|
||||
"SubMenu21": "孙菜单 21",
|
||||
"SubMenu22": "孙菜单 22",
|
||||
"SubMenu31": "曾孙菜单 31",
|
||||
"SubMenu32": "曾孙菜单 32",
|
||||
"SubMenu41": "曾曾孙菜单 41",
|
||||
"SubMenu42": "曾曾孙菜单 42"
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,7 @@
|
||||
@inherits BootstrapComponentBase
|
||||
@inject IOptions<BootstrapBlazorOptions> BootstrapOptions
|
||||
@inject NavigationManager NavigationManager
|
||||
@inject ICultureStorage CultureStorage
|
||||
|
||||
<div @attributes="@AdditionalAttributes" class="@ClassString">
|
||||
<label>请选择语言:</label>
|
||||
<label>@Label</label>
|
||||
<Select Value="@SelectedCulture" OnSelectedItemChanged="@SetCulture">
|
||||
<Options>
|
||||
@foreach (var kv in BootstrapOptions.Value.GetSupportedCultures())
|
||||
@@ -14,55 +11,3 @@
|
||||
</Options>
|
||||
</Select>
|
||||
</div>
|
||||
|
||||
@code{
|
||||
private string? ClassString => CssBuilder.Default("culture-selector")
|
||||
.AddClassFromAttributes(AdditionalAttributes)
|
||||
.Build();
|
||||
|
||||
private string SelectedCulture { get; set; } = CultureInfo.CurrentUICulture.Name;
|
||||
|
||||
private async Task SetCulture(SelectedItem item)
|
||||
{
|
||||
if (CultureStorage.Mode == CultureStorageMode.Webapi)
|
||||
{
|
||||
// 使用 api 方式 适用于 Server-Side 模式
|
||||
if (SelectedCulture != item.Value)
|
||||
{
|
||||
var culture = item.Value;
|
||||
var uri = new Uri(NavigationManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
|
||||
var query = $"?culture={Uri.EscapeDataString(culture)}&redirectUri={Uri.EscapeDataString(uri)}";
|
||||
|
||||
// use a path that matches your culture redirect controller from the previous steps
|
||||
NavigationManager.NavigateTo("/Culture/SetCulture" + query, forceLoad: true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var cultureName = item.Value;
|
||||
if (cultureName != CultureInfo.CurrentCulture.Name)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync(identifier: "$.blazorCulture.set", cultureName);
|
||||
var culture = new CultureInfo(cultureName);
|
||||
CultureInfo.CurrentCulture = culture;
|
||||
CultureInfo.CurrentUICulture = culture;
|
||||
|
||||
NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string GetDisplayName(CultureInfo culture)
|
||||
{
|
||||
return CultureStorage.Mode switch
|
||||
{
|
||||
CultureStorageMode.Webapi => culture.NativeName,
|
||||
_ => culture.Name switch
|
||||
{
|
||||
"zh-CN" => "中文(中国)",
|
||||
"en-US" => "English (United States)",
|
||||
_ => ""
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.JSInterop;
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages.Components
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public partial class CultureChooser
|
||||
{
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IOptions<BootstrapBlazorOptions>? BootstrapOptions { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IStringLocalizer<CultureChooser>? Localizer { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private NavigationManager? NavigationManager { get; set; }
|
||||
|
||||
private string? ClassString => CssBuilder.Default("culture-selector")
|
||||
.AddClassFromAttributes(AdditionalAttributes)
|
||||
.Build();
|
||||
|
||||
private string SelectedCulture { get; set; } = CultureInfo.CurrentUICulture.Name;
|
||||
|
||||
[NotNull]
|
||||
private string? Label { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// OnInitialized 方法
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
Label ??= Localizer[nameof(Label)];
|
||||
}
|
||||
|
||||
private async Task SetCulture(SelectedItem item)
|
||||
{
|
||||
if (OperatingSystem.IsBrowser())
|
||||
{
|
||||
var cultureName = item.Value;
|
||||
if (cultureName != CultureInfo.CurrentCulture.Name)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync(identifier: "$.blazorCulture.set", cultureName);
|
||||
var culture = new CultureInfo(cultureName);
|
||||
CultureInfo.CurrentCulture = culture;
|
||||
CultureInfo.CurrentUICulture = culture;
|
||||
|
||||
NavigationManager.NavigateTo(NavigationManager.Uri, forceLoad: true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 使用 api 方式 适用于 Server-Side 模式
|
||||
if (SelectedCulture != item.Value)
|
||||
{
|
||||
var culture = item.Value;
|
||||
var uri = new Uri(NavigationManager.Uri).GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
|
||||
var query = $"?culture={Uri.EscapeDataString(culture)}&redirectUri={Uri.EscapeDataString(uri)}";
|
||||
|
||||
// use a path that matches your culture redirect controller from the previous steps
|
||||
NavigationManager.NavigateTo("/Culture/SetCulture" + query, forceLoad: true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetDisplayName(CultureInfo culture)
|
||||
{
|
||||
string? ret;
|
||||
if (OperatingSystem.IsBrowser())
|
||||
{
|
||||
ret = culture.Name switch
|
||||
{
|
||||
"zh-CN" => "中文(中国)",
|
||||
"en-US" => "English (United States)",
|
||||
_ => ""
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = culture.NativeName;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,45 +4,7 @@
|
||||
<Select TValue="string" Items="@Items3" OnSelectedItemChanged="@OnCascadeBindSelectClick" />
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select @ref="Select2" TValue="string" Items="@Items2" />
|
||||
<Select TValue="string" Items="@Items2" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@code {
|
||||
private Select<string>? Select2;
|
||||
private readonly List<SelectedItem> Items2 = new List<SelectedItem>();
|
||||
private readonly IEnumerable<SelectedItem> Items3 = new SelectedItem[]
|
||||
{
|
||||
new SelectedItem ("", "请选择 ..."),
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海")
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 级联绑定菜单
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
private Task OnCascadeBindSelectClick(SelectedItem item)
|
||||
{
|
||||
Items2.Clear();
|
||||
if (item.Value == "Beijing")
|
||||
{
|
||||
Items2.AddRange(new SelectedItem[]
|
||||
{
|
||||
new SelectedItem("1","朝阳区"),
|
||||
new SelectedItem("2","海淀区"),
|
||||
});
|
||||
}
|
||||
else if (item.Value == "Shanghai")
|
||||
{
|
||||
Items2.AddRange(new SelectedItem[]
|
||||
{
|
||||
new SelectedItem("1","静安区"),
|
||||
new SelectedItem("2","黄浦区"),
|
||||
});
|
||||
}
|
||||
Select2?.SetItems(Items2);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages.Components
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public partial class CustomerSelectDialog
|
||||
{
|
||||
private IEnumerable<SelectedItem>? Items2;
|
||||
private readonly IEnumerable<SelectedItem> Items3 = new SelectedItem[]
|
||||
{
|
||||
new SelectedItem ("", "请选择 ..."),
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海")
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 级联绑定菜单
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
private async Task OnCascadeBindSelectClick(SelectedItem item)
|
||||
{
|
||||
// 模拟异步通讯获取数据
|
||||
await Task.Delay(100);
|
||||
if (item.Value == "Beijing")
|
||||
{
|
||||
Items2 = new SelectedItem[]
|
||||
{
|
||||
new SelectedItem("1","朝阳区"),
|
||||
new SelectedItem("2","海淀区"),
|
||||
};
|
||||
}
|
||||
else if (item.Value == "Shanghai")
|
||||
{
|
||||
Items2 = new SelectedItem[]
|
||||
{
|
||||
new SelectedItem("1","静安区"),
|
||||
new SelectedItem("2","黄浦区"),
|
||||
};
|
||||
}
|
||||
else
|
||||
{
|
||||
Items2 = Enumerable.Empty<SelectedItem>();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,13 +12,6 @@
|
||||
<EditorForm TModel="Foo">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.Id" Editable="false" />
|
||||
<EditorItem @bind-Field="@context.Complete">
|
||||
<EditTemplate Context="value">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Switch @bind-Value="@(((Foo)value).Complete)" ShowInnerText="true" OnInnerText="是" OffInnerText="否" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@context.Hobby" Data="@Hobbys" />
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
|
||||
16
src/BootstrapBlazor.Shared/Pages/Components/DialogDemo.razor
Normal file
@@ -0,0 +1,16 @@
|
||||
<h3>无限弹窗示例</h3>
|
||||
|
||||
<Tab>
|
||||
<TabItem Text="用户管理">
|
||||
<div>我是用户管理 @Value</div>
|
||||
<Button Text="弹窗" OnClick="@OnClickButton" />
|
||||
</TabItem>
|
||||
<TabItem Text="菜单管理">
|
||||
<div>我是菜单管理</div>
|
||||
<Button Text="弹窗" OnClick="@OnClickButton" />
|
||||
</TabItem>
|
||||
<TabItem Text="角色管理">
|
||||
<div>我是角色管理</div>
|
||||
<Button Text="弹窗" OnClick="@OnClickButton" />
|
||||
</TabItem>
|
||||
</Tab>
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages.Components
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public partial class DialogDemo
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
public string? Value { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private DialogService? DialogService { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// OnInitialized 方法
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
Value = DateTime.Now.ToString();
|
||||
}
|
||||
|
||||
private Task OnClickButton() => DialogService.Show(new DialogOption()
|
||||
{
|
||||
Title = $"弹窗 {Value}",
|
||||
Component = BootstrapDynamicComponent.CreateComponent<DialogDemo>()
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ namespace BootstrapBlazor.Shared.Pages.Components
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Key]
|
||||
[Display(Name = "主键")]
|
||||
[AutoGenerateColumn(Ignore = true)]
|
||||
public int Id { get; set; }
|
||||
@@ -60,7 +61,7 @@ namespace BootstrapBlazor.Shared.Pages.Components
|
||||
///
|
||||
/// </summary>
|
||||
[Display(Name = "是/否")]
|
||||
[AutoGenerateColumn(Order = 50)]
|
||||
[AutoGenerateColumn(Order = 50, ComponentType = typeof(Switch))]
|
||||
public bool Complete { get; set; }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<Table TItem="Foo" Items="@Items.Take(10)" ClickToSelect="true" IsMultipleSelect="true" @bind-SelectedRows="@SelectedRows">
|
||||
<Table TItem="Foo" ClickToSelect="true" IsMultipleSelect="true" @bind-SelectedRows="@SelectedRows" OnQueryAsync="@OnQueryAsync">
|
||||
<TableColumns>
|
||||
<TableColumn @bind-Field="@context.Id" />
|
||||
<TableColumn @bind-Field="@context.Name" />
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace BootstrapBlazor.Shared.Pages.Components
|
||||
public EventCallback<IEnumerable<string>> EmailsChanged { get; set; }
|
||||
|
||||
[CascadingParameter(Name = "BodyContext")]
|
||||
private object? Count { get; set; }
|
||||
private object? BodyContext { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
@@ -50,12 +50,19 @@ namespace BootstrapBlazor.Shared.Pages.Components
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
Items = GenerateItems((int)(Count ?? 10));
|
||||
Emails ??= Array.Empty<string>();
|
||||
var context = BodyContext as FooContext;
|
||||
Items = GenerateItems(context?.Count ?? 10);
|
||||
Emails = context?.Emails?.Split(";") ?? Array.Empty<string>();
|
||||
|
||||
SelectedRows = Items.Where(i => Emails.Any(mail => mail == i.Email));
|
||||
}
|
||||
|
||||
private Task<QueryData<Foo>> OnQueryAsync(QueryPageOptions option) => Task.FromResult(new QueryData<Foo>()
|
||||
{
|
||||
TotalCount = Items.Count(),
|
||||
Items = Items
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
@@ -93,7 +100,7 @@ namespace BootstrapBlazor.Shared.Pages.Components
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected static List<Foo> GenerateItems(int startId) => new List<Foo>(Enumerable.Range(startId, 10).Select(i => new Foo()
|
||||
private static List<Foo> GenerateItems(int startId) => new(Enumerable.Range(startId, 10).Select(i => new Foo()
|
||||
{
|
||||
Id = i,
|
||||
Name = $"张三 {i:d4}",
|
||||
@@ -103,7 +110,23 @@ namespace BootstrapBlazor.Shared.Pages.Components
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public class Foo
|
||||
public class FooContext
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public int Count { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public string? Emails { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private class Foo
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
|
||||
@@ -1,10 +1,4 @@
|
||||
@if (Count > 0)
|
||||
{
|
||||
<Badge Color="@BootstrapBlazor.Components.Color.Info" IsPill="true">
|
||||
@Count
|
||||
</Badge>
|
||||
}
|
||||
@if (IsNew)
|
||||
@if (IsNew)
|
||||
{
|
||||
<span class="badge badge-danger">
|
||||
<span>NEW</span>
|
||||
@@ -16,3 +10,9 @@
|
||||
<span>Upd</span>
|
||||
</span>
|
||||
}
|
||||
@if (Count > 0)
|
||||
{
|
||||
<Badge Color="@BootstrapBlazor.Components.Color.Info" IsPill="true">
|
||||
@Count
|
||||
</Badge>
|
||||
}
|
||||
|
||||
@@ -39,9 +39,10 @@
|
||||
<ComponentCard Text="表单组件 ValidateForm" Image="ValidateForm.png" Url="validateforms"></ComponentCard>
|
||||
<ComponentCard Text="自动完成 AutoComplete" Image="AutoComplete.svg" Url="autocompletes"></ComponentCard>
|
||||
<ComponentCard Text="按钮 Button" Image="Button.svg" Url="buttons"></ComponentCard>
|
||||
<ComponentCard Text="级联选择 Button" Image="Cascader.svg" Url="cascaders"></ComponentCard>
|
||||
<ComponentCard Text="级联选择 Cascader" Image="Cascader.png" Url="cascaders"></ComponentCard>
|
||||
<ComponentCard Text="多选框 Checkbox" Image="CheckBox.svg" Url="checkboxs"></ComponentCard>
|
||||
<ComponentCard Text="多选框组 CheckboxList" Image="CheckboxList.png" Url="checkboxlists"></ComponentCard>
|
||||
<ComponentCard Text="颜色拾取器 ColorPicker" Image="ColorPicker.png" Url="colorpickers"></ComponentCard>
|
||||
<ComponentCard Text="时间框 DateTimePicker" Image="DatePicker.svg" Url="datetimepickers"></ComponentCard>
|
||||
<ComponentCard Text="时间范围框 DateTimeRange" Image="DateTimeRange.png" Url="datetimeranges"></ComponentCard>
|
||||
<ComponentCard Text="富文本框 Editor" Image="Editor.png" Url="editors"></ComponentCard>
|
||||
@@ -98,7 +99,7 @@
|
||||
<ComponentCard Text="确认框 Popconfirm" Image="Popconfirm.svg" Url="popconfirms"></ComponentCard>
|
||||
<ComponentCard Text="进度条 Progress" Image="Progress.svg" Url="progresss"></ComponentCard>
|
||||
<ComponentCard Text="旋转图标 Spinner" Image="Spinner.gif" Url="spinners"></ComponentCard>
|
||||
<ComponentCard Text="弹窗组件 SweetAlert" Image="SweetAlert.png" Url="swals"></ComponentCard>
|
||||
<ComponentCard Text="模态弹窗 SweetAlert" Image="SweetAlert.png" Url="swals"></ComponentCard>
|
||||
<ComponentCard Text="搜索弹窗 SearchDialog" Image="SearchDialog.png" Url="searchdialogs"></ComponentCard>
|
||||
<ComponentCard Text="轻量弹窗 Toast" Image="Toast.png" Url="toasts"></ComponentCard>
|
||||
<ComponentCard Text="计时器 Timer" Image="Timer.png" Url="timers"></ComponentCard>
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
@using Microsoft.Extensions.Localization
|
||||
@layout HomeLayout
|
||||
@layout HomeLayout
|
||||
@page "/"
|
||||
@page "/index"
|
||||
@page "/home"
|
||||
|
||||
<Title Text="@Localizer["Title"]"></Title>
|
||||
|
||||
<section class="home-section">
|
||||
<div class="welcome container">
|
||||
<div class="form-inline">
|
||||
@@ -13,7 +14,7 @@
|
||||
<h4>
|
||||
Bootstrap 风格的 Blazor UI 组件库
|
||||
</h4>
|
||||
<div>基于 <code>Bootstrap</code> 样式库精心打造,并且额外增加了 76 多种常用的组件,为您快速开发项目带来非一般的感觉</div>
|
||||
<div>基于 <code>Bootstrap</code> 样式库精心打造,并且额外增加了 @Options.Value.TotalCount 多种常用的组件,为您快速开发项目带来非一般的感觉</div>
|
||||
<div class="welcome-body">
|
||||
致力于打造全网<span @ref="TypeElement" class="typed"></span><span class="typed-cursor">|</span>
|
||||
<div>最好玩的组件库</div>
|
||||
@@ -127,8 +128,8 @@
|
||||
<p class="d-none d-sm-block">
|
||||
<img src="_content/BootstrapBlazor.Shared/images/components.svg" alt="components" />
|
||||
</p>
|
||||
<h3>50+ 组件</h3>
|
||||
<div>本套组件库包含超过 50 多个组件,从简单的按钮到复杂的整页面级别的组件</div>
|
||||
<h3>丰富组件</h3>
|
||||
<div>本套组件库包含超过 @Options.Value.TotalCount 多个组件,从简单的按钮到复杂的整页面级别的组件</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6 col-md-4">
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Microsoft.JSInterop;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
@@ -18,6 +21,14 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
[Inject]
|
||||
private IJSRuntime? JSRuntime { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IStringLocalizer<App>? Localizer { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IOptions<WebsiteOptions>? Options { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
@@ -27,7 +38,10 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
|
||||
if (firstRender && JSRuntime != null) await JSRuntime.InvokeVoidAsync("$.indexTyper", TypeElement);
|
||||
if (firstRender && JSRuntime != null)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("$.indexTyper", TypeElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
@page "/docs"
|
||||
@page "/introduction"
|
||||
@inject IOptions<WebsiteOptions> WebsiteOption
|
||||
|
||||
<h3>简介</h3>
|
||||
|
||||
<p>BootstrapBlazor 是一套基于 Bootstrap 和 Blazor 的企业级组件库,可以认为是 Bootstrap 项目的 Blazor 版实现。</p>
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
<Block Title="展示类型" Introduction="支持三种类型:图标、图片和字符">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<Avatar IsCircle="true" IsIcon="true" />
|
||||
<Avatar IsCircle="true" IsIcon="true" Icon="fa fa-user" />
|
||||
<Avatar IsCircle="true" Url="_content/BootstrapBlazor.Shared/images/Argo-C.png" />
|
||||
<Avatar IsCircle="true" IsText="true" Text="User" />
|
||||
</div>
|
||||
@@ -47,4 +47,10 @@
|
||||
<div>第二幅圆形头像加载图片路径错误,所以边框为 <b class="text-danger">红色</b>,图片显示为默认图标</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="异步加载" Introduction="适用于图片地址由 <code>webapi</code> 等接口异步获取的场景">
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<Avatar IsCircle="true" GetUrlAsync="@GetUrlAsync" />
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" />
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
using BootstrapBlazor.Shared.Common;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
@@ -12,11 +13,17 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// </summary>
|
||||
public sealed partial class Avatars
|
||||
{
|
||||
private async Task<string> GetUrlAsync()
|
||||
{
|
||||
// 模拟异步获取图像地址
|
||||
await Task.Delay(500);
|
||||
return "_content/BootstrapBlazor.Shared/images/Argo-C.png";
|
||||
}
|
||||
/// <summary>
|
||||
/// 获得属性方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new[]
|
||||
{
|
||||
// TODO: 移动到数据库中
|
||||
new AttributeItem() {
|
||||
@@ -74,6 +81,13 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
Type = "string",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "GetUrlAsync",
|
||||
Description = "获取 Image 头像路径地址异步回调委托",
|
||||
Type = "Func<Task<string>>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -154,6 +154,15 @@
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="异步请求按钮" Introduction="通过设置 <code>IsAsync</code> 属性按钮是否为 <b>异步请求按钮</b>,默认为 <code>false</code>">
|
||||
<p>当按钮为异步请求按钮时,点击按钮后自身状态会改变为禁用状态,同时显示 <code>Loading</code> 小图标,异步请求结束后恢复正常,本例中点击 <b>异步请求</b>按钮后,显示请求加载动画,5 秒后恢复正常</p>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<Button Text="异步请求" IsAsync="true" Icon="fa fa-fw fa-fa" OnClick="@ClickAsyncButton" />
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" />
|
||||
|
||||
<EventTable Items="@GetEvents()" />
|
||||
|
||||
@@ -58,11 +58,13 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private static Task ClickAsyncButton() => Task.Delay(5000);
|
||||
|
||||
/// <summary>
|
||||
/// 获得事件方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<EventItem> GetEvents() => new EventItem[]
|
||||
private static IEnumerable<EventItem> GetEvents() => new EventItem[]
|
||||
{
|
||||
new EventItem()
|
||||
{
|
||||
@@ -82,7 +84,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// 获得属性方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
{
|
||||
// TODO: 移动到数据库中
|
||||
new AttributeItem() {
|
||||
@@ -99,6 +101,13 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
ValueList = "",
|
||||
DefaultValue = ""
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "LoadingIcon",
|
||||
Description = "异步加载时的动画图标",
|
||||
Type = "string",
|
||||
ValueList = "",
|
||||
DefaultValue = "fa fa-fw fa-spin fa-spinner"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "Text",
|
||||
Description = "显示文字",
|
||||
@@ -141,6 +150,13 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
ValueList = " — ",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "IsAsync",
|
||||
Description = "是否为异步按钮",
|
||||
Type = "boolean",
|
||||
ValueList = " — ",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "ChildContent",
|
||||
Description = "内容",
|
||||
|
||||
@@ -70,7 +70,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// 获得属性方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new[]
|
||||
{
|
||||
// TODO: 移动到数据库中
|
||||
new AttributeItem() {
|
||||
@@ -149,7 +149,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// 获得事件方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<EventItem> GetEvents() => new EventItem[]
|
||||
private static IEnumerable<EventItem> GetEvents() => new[]
|
||||
{
|
||||
new EventItem()
|
||||
{
|
||||
@@ -163,7 +163,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// 获得事件方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<MethodItem> GetMethods() => new MethodItem[]
|
||||
private static IEnumerable<MethodItem> GetMethods() => new[]
|
||||
{
|
||||
new MethodItem()
|
||||
{
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
if (firstRender && JSRuntime != null)
|
||||
{
|
||||
if (Interope == null) Interope = new JSInterop<Charts>(JSRuntime);
|
||||
await Interope.Invoke(this, "", "_initChart", nameof(ShowToast));
|
||||
await Interope.InvokeVoidAsync(this, "", "_initChart", nameof(ShowToast));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -96,6 +96,16 @@
|
||||
</ValidateForm>
|
||||
</Block>
|
||||
|
||||
<Block Title="禁用" Introduction="通过设置 <code>IsDisabled=true</code> 禁用">
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12">
|
||||
<CheckboxList @bind-Value="@Dummy.Name" IsDisabled="true" ShowBorder="false" Items="@Items2" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" />
|
||||
|
||||
<EventTable Items="@GetEvents()" />
|
||||
|
||||
@@ -93,26 +93,30 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
|
||||
private Foo Dummy { get; set; } = new Foo() { Name = "张三,李四" };
|
||||
|
||||
private static IEnumerable<AttributeItem> GetAttributes()
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
{
|
||||
return new AttributeItem[]
|
||||
{
|
||||
new AttributeItem() {
|
||||
Name = "Items",
|
||||
Description = "数据源",
|
||||
Type = "IEnumerable<SelectedItem>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem(){
|
||||
Name = "Value",
|
||||
Description = "组件值用于双向绑定",
|
||||
Type = "TValue",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
}
|
||||
};
|
||||
}
|
||||
new AttributeItem() {
|
||||
Name = "Items",
|
||||
Description = "数据源",
|
||||
Type = "IEnumerable<SelectedItem>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "IsDisabled",
|
||||
Description = "是否禁用",
|
||||
Type = "boolean",
|
||||
ValueList = " — ",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem(){
|
||||
Name = "Value",
|
||||
Description = "组件值用于双向绑定",
|
||||
Type = "TValue",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 获得事件方法
|
||||
|
||||
@@ -31,6 +31,31 @@
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="颜色" Introduction="通过设置 <code>Color</code> 属性改变组件背景色">
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-md-4">
|
||||
<Checkbox TValue="string" State="CheckboxState.Checked" DisplayText="选中" ShowLabel="true" Color="@Color.Primary"></Checkbox>
|
||||
</div>
|
||||
<div class="form-group col-12 col-md-4">
|
||||
<Checkbox TValue="string" State="CheckboxState.Checked" DisplayText="选中" ShowLabel="true" Color="@Color.Success"></Checkbox>
|
||||
</div>
|
||||
<div class="form-group col-12 col-md-4">
|
||||
<Checkbox TValue="string" State="CheckboxState.Checked" DisplayText="选中" ShowLabel="true" Color="@Color.Danger"></Checkbox>
|
||||
</div>
|
||||
<div class="form-group col-12 col-md-4">
|
||||
<Checkbox TValue="string" State="CheckboxState.Checked" DisplayText="选中" ShowLabel="true" Color="@Color.Info"></Checkbox>
|
||||
</div>
|
||||
<div class="form-group col-12 col-md-4">
|
||||
<Checkbox TValue="string" State="CheckboxState.Checked" DisplayText="选中" ShowLabel="true" Color="@Color.Warning"></Checkbox>
|
||||
</div>
|
||||
<div class="form-group col-12 col-md-4">
|
||||
<Checkbox TValue="string" State="CheckboxState.Checked" DisplayText="选中" ShowLabel="true" Color="@Color.Dark"></Checkbox>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="Label 文字" Introduction="复选框显示文字,通过 <code>DisplayText</code> 设置组件显示文本,点击显示文字时组件状态也会进行翻转">
|
||||
<p>设置<code>DisplayText</code> 属性,或者通过双向绑定均可以显示文本信息</p>
|
||||
<div class="form-inline">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<h4>通过折叠面板收纳内容区域</h4>
|
||||
|
||||
<Block Title="基础用法" Introduction="可同时展开多个面板,面板之间不影响">
|
||||
<Collapse>
|
||||
<Collapse OnCollapseChanged="@OnChanged">
|
||||
<CollapseItems>
|
||||
<CollapseItem Text="一致性 Consistency">
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
@@ -26,6 +26,7 @@
|
||||
</CollapseItem>
|
||||
</CollapseItems>
|
||||
</Collapse>
|
||||
<Logger @ref="Trace" class="mt-3" />
|
||||
</Block>
|
||||
|
||||
<Block Title="指示箭头" Introduction="右侧显示指示箭头">
|
||||
@@ -53,7 +54,7 @@
|
||||
</Block>
|
||||
|
||||
<Block Title="手风琴效果" Introduction="每次只能展开一个面板">
|
||||
<Collapse ShowArrow="true" IsAccordion ="true">
|
||||
<Collapse ShowArrow="true" IsAccordion="true">
|
||||
<CollapseItems>
|
||||
<CollapseItem Text="一致性 Consistency">
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
@@ -76,4 +77,28 @@
|
||||
</Collapse>
|
||||
</Block>
|
||||
|
||||
<Block Title="子项标题颜色" Introduction="每个面板设置不同颜色">
|
||||
<Collapse ShowArrow="true" IsAccordion="true">
|
||||
<CollapseItems>
|
||||
<CollapseItem Text="一致性 Consistency" TitleColor="Color.Primary">
|
||||
<div>与现实生活一致:与现实生活的流程、逻辑保持一致,遵循用户习惯的语言和概念;</div>
|
||||
<div>在界面中一致:所有的元素和结构需保持一致,比如:设计样式、图标和文本、元素的位置等。</div>
|
||||
</CollapseItem>
|
||||
<CollapseItem Text="反馈 Feedback" TitleColor="Color.Info">
|
||||
<div>控制反馈:通过界面样式和交互动效让用户可以清晰的感知自己的操作;</div>
|
||||
<div>页面反馈:操作后,通过页面元素的变化清晰地展现当前状态。</div>
|
||||
</CollapseItem>
|
||||
<CollapseItem Text="效率 Efficiency" TitleColor="Color.Success">
|
||||
<div>简化流程:设计简洁直观的操作流程;</div>
|
||||
<div>清晰明确:语言表达清晰且表意明确,让用户快速理解进而作出决策;</div>
|
||||
<div>帮助用户识别:界面简单直白,让用户快速识别而非回忆,减少用户记忆负担。</div>
|
||||
</CollapseItem>
|
||||
<CollapseItem Text="可控 Controllability" TitleColor="Color.Warning">
|
||||
<div>用户决策:根据场景可给予用户操作建议或安全提示,但不能代替用户进行决策;</div>
|
||||
<div>结果可控:用户可以自由的进行操作,包括撤销、回退和终止当前操作等。</div>
|
||||
</CollapseItem>
|
||||
</CollapseItems>
|
||||
</Collapse>
|
||||
</Block>
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" />
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using BootstrapBlazor.Shared.Common;
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
@@ -14,18 +16,13 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// </summary>
|
||||
public sealed partial class Collapses
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
private Logger? Trace { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
private void ButtonClick(MouseEventArgs e)
|
||||
private Task OnChanged(CollapseItem item)
|
||||
{
|
||||
Trace?.Log($"Button Clicked");
|
||||
Trace.Log($"{item.Text}: {item.IsCollapsed}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -17,13 +17,9 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// </summary>
|
||||
public sealed partial class Consoles : IDisposable
|
||||
{
|
||||
private readonly BlockingCollection<ConsoleMessageItem> _messages = new BlockingCollection<ConsoleMessageItem>(new ConcurrentQueue<ConsoleMessageItem>());
|
||||
private readonly BlockingCollection<ConsoleMessageItem> _messages2 = new BlockingCollection<ConsoleMessageItem>(new ConcurrentQueue<ConsoleMessageItem>());
|
||||
|
||||
private readonly CancellationTokenSource _cancelTokenSource = new CancellationTokenSource();
|
||||
|
||||
private IEnumerable<ConsoleMessageItem> Messages => _messages;
|
||||
private IEnumerable<ConsoleMessageItem> ColorMessages => _messages2;
|
||||
private ConcurrentQueue<ConsoleMessageItem> Messages { get; set; } = new();
|
||||
private ConcurrentQueue<ConsoleMessageItem> ColorMessages { get; set; } = new();
|
||||
private readonly CancellationTokenSource _cancelTokenSource = new();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
@@ -38,23 +34,20 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
do
|
||||
{
|
||||
_locker.WaitOne();
|
||||
if (!_messages.IsAddingCompleted)
|
||||
Messages.Enqueue(new ConsoleMessageItem { Message = $"{DateTimeOffset.Now}: Dispatch Message" });
|
||||
|
||||
ColorMessages.Enqueue(new ConsoleMessageItem { Message = $"{DateTimeOffset.Now}: Dispatch Message", Color = GetColor() });
|
||||
|
||||
if (Messages.Count > 8)
|
||||
{
|
||||
_messages.Add(new ConsoleMessageItem { Message = $"{DateTimeOffset.Now}: Dispatch Message" });
|
||||
|
||||
_messages2.Add(new ConsoleMessageItem { Message = $"{DateTimeOffset.Now}: Dispatch Message", Color = GetColor() });
|
||||
|
||||
if (_messages.Count > 8)
|
||||
{
|
||||
_messages.TryTake(out var _);
|
||||
}
|
||||
|
||||
if (_messages2.Count > 12)
|
||||
{
|
||||
_messages2.TryTake(out var _);
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
Messages.TryDequeue(out var _);
|
||||
}
|
||||
|
||||
if (ColorMessages.Count > 12)
|
||||
{
|
||||
ColorMessages.TryDequeue(out var _);
|
||||
}
|
||||
await InvokeAsync(StateHasChanged);
|
||||
_locker.Set();
|
||||
await Task.Delay(2000, _cancelTokenSource.Token);
|
||||
}
|
||||
@@ -62,7 +55,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
});
|
||||
}
|
||||
|
||||
private Color GetColor()
|
||||
private static Color GetColor()
|
||||
{
|
||||
var second = DateTime.Now.Second;
|
||||
return (second % 3) switch
|
||||
@@ -73,22 +66,19 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
};
|
||||
}
|
||||
|
||||
private readonly AutoResetEvent _locker = new AutoResetEvent(true);
|
||||
private readonly AutoResetEvent _locker = new(true);
|
||||
|
||||
private void OnClear()
|
||||
{
|
||||
_locker.WaitOne();
|
||||
if (!_messages.IsAddingCompleted)
|
||||
while (!Messages.IsEmpty)
|
||||
{
|
||||
while (_messages.Count > 0)
|
||||
{
|
||||
_messages.TryTake(out var _);
|
||||
}
|
||||
Messages.TryDequeue(out var _);
|
||||
}
|
||||
_locker.Set();
|
||||
}
|
||||
|
||||
private IEnumerable<AttributeItem> GetItemAttributes()
|
||||
private static IEnumerable<AttributeItem> GetItemAttributes()
|
||||
{
|
||||
return new AttributeItem[]
|
||||
{
|
||||
@@ -113,7 +103,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<AttributeItem> GetAttributes()
|
||||
private static IEnumerable<AttributeItem> GetAttributes()
|
||||
{
|
||||
return new AttributeItem[]
|
||||
{
|
||||
@@ -187,7 +177,6 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_messages.CompleteAdding();
|
||||
_cancelTokenSource.Cancel();
|
||||
_cancelTokenSource.Dispose();
|
||||
}
|
||||
|
||||
@@ -4,23 +4,22 @@
|
||||
|
||||
<h4>通过注入服务调用 <code>Show</code> 方法弹出窗口进行人机交互</h4>
|
||||
|
||||
<Tips class="mt-3">
|
||||
<p>
|
||||
本组件使用注入服务的形式提供功能,使用时用户体验效果非常舒适,随时随地的调用,需要在使用本组件的页面中内置 <code>Dialog</code> 组件,或者在 <code>MainLayout</code> 主布局组件中内置,示例代码如下:
|
||||
</p>
|
||||
</Tips>
|
||||
|
||||
<Pre><Dialog /></Pre>
|
||||
|
||||
<Block Title="基本用法" Introduction="通过设置 <code>DialogOption</code> 属性对模态框进行基本属性设置">
|
||||
<Button @onclick="@OnClick">点击打开 Dialog</Button>
|
||||
</Block>
|
||||
|
||||
<Block Title="弹出复杂组件" Introduction="通过调用 <code>Show<Counter>()</code> 来弹出一个自定义组件">
|
||||
<p>
|
||||
本例中弹出对话框中包含一个示例网站的自带 <code>Counter</code> 组件,通过设置 <code>KeepChildrenState</code> 属性来控制弹窗内组件是否保持状态
|
||||
<ul class="ul-demo">
|
||||
<li>选择 <b>不保持状态</b> 时,弹窗内的计数器数据关闭弹窗后清零</li>
|
||||
<li>选择 <b>保持状态</b> 时,弹窗内的计数器数据关闭弹窗后保持</li>
|
||||
</ul>
|
||||
本例中弹出对话框中包含一个示例网站的自带 <code>Counter</code> 组件
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<Radio Items="@RadioItems" OnStateChanged="@OnStateChanged" />
|
||||
</p>
|
||||
|
||||
<Button @onclick="@OnClickCounter">点击打开 Dialog</Button>
|
||||
</Block>
|
||||
|
||||
@@ -64,16 +63,15 @@
|
||||
</Block>
|
||||
|
||||
<Block Title="多级弹窗" Introduction="点击弹窗内部按钮继续弹出对话窗">
|
||||
<Tips>
|
||||
<div>通过嵌套调用注入的 <code>DialogService</code> 实例弹出对话窗,组件内部通过 <code>LIFO</code> 模式后弹先关的顺序对弹窗排序;通过此功能即可实现 <code>无限弹窗</code></div>
|
||||
</Tips>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<Button OnClick="@ShowDialogLoop">弹窗</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>功能介绍</p>
|
||||
<ul class="ul-demo">
|
||||
<li>点击按钮弹出对话窗</li>
|
||||
<li>切换弹窗内 <code>Tab</code> 组件的第三个标签页 <b>角色管理</b></li>
|
||||
<li>点击标签页中的弹窗继续弹出对话框</li>
|
||||
<li>关闭当前对话框后之前打开的对话框 <b>保持状态</b></li>
|
||||
</ul>
|
||||
|
||||
<Button OnClick="@ShowDialogLoop">弹窗</Button>
|
||||
</Block>
|
||||
|
||||
<Block Title="模态对话框" Introduction="通过 <code>ShowModal</code> 方法弹出线程阻塞模式的对话框">
|
||||
@@ -110,12 +108,4 @@
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Tips class="mt-3">
|
||||
<p>
|
||||
本组件使用注入服务的形式提供功能,使用时用户体验效果非常舒适,随时随地的调用,需要在使用本组件的页面中内置 <code>Dialog</code> 组件,或者在 <code>MainLayout</code> 主布局组件中内置,示例代码如下:
|
||||
</p>
|
||||
</Tips>
|
||||
|
||||
<Pre><Dialog /></Pre>
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" Title="DialogOption 属性" />
|
||||
|
||||
@@ -15,36 +15,20 @@ using System.Threading.Tasks;
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// 弹窗组件示例代码
|
||||
/// </summary>
|
||||
public sealed partial class Dialogs
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private IEnumerable<SelectedItem> RadioItems { get; set; } = new SelectedItem[] {
|
||||
new SelectedItem("false", "不保持状态") { Active = true },
|
||||
new SelectedItem("true", "保持状态")
|
||||
};
|
||||
|
||||
[NotNull]
|
||||
private Logger? Trace { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// 获得 弹窗注入服务
|
||||
/// </summary>
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private DialogService? DialogService { get; set; }
|
||||
|
||||
private Task OnStateChanged(CheckboxState state, SelectedItem item)
|
||||
{
|
||||
KeepState = bool.Parse(item.Value);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private bool KeepState { get; set; }
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
@@ -52,9 +36,9 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
private Task OnClick() => DialogService.Show(new DialogOption()
|
||||
{
|
||||
Title = "我是服务创建的弹出框",
|
||||
BodyTemplate = DynamicComponent.CreateComponent<Button>(new KeyValuePair<string, object>[]
|
||||
BodyTemplate = BootstrapDynamicComponent.CreateComponent<Button>(new[]
|
||||
{
|
||||
new KeyValuePair<string, object>(nameof(Button.ChildContent), new RenderFragment(builder => builder.AddContent(0, "我是服务创建的按钮")))
|
||||
new KeyValuePair<string, object?>(nameof(Button.ChildContent), new RenderFragment(builder => builder.AddContent(0, "我是服务创建的按钮")))
|
||||
})
|
||||
.Render()
|
||||
});
|
||||
@@ -65,10 +49,10 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
Title = "利用代码关闭弹出框",
|
||||
};
|
||||
option.BodyTemplate = DynamicComponent.CreateComponent<Button>(new KeyValuePair<string, object>[]
|
||||
option.BodyTemplate = BootstrapDynamicComponent.CreateComponent<Button>(new[]
|
||||
{
|
||||
new KeyValuePair<string, object>(nameof(Button.Text), "点击关闭弹窗"),
|
||||
new KeyValuePair<string, object>(nameof(Button.OnClick), EventCallback.Factory.Create<MouseEventArgs>(this, async () => await option.Dialog.Close()))
|
||||
new KeyValuePair<string, object?>(nameof(Button.Text), "点击关闭弹窗"),
|
||||
new KeyValuePair<string, object?>(nameof(Button.OnClick), EventCallback.Factory.Create<MouseEventArgs>(this, async () => await option.Dialog.Close()))
|
||||
}).Render();
|
||||
await DialogService.Show(option);
|
||||
}
|
||||
@@ -80,8 +64,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
private Task OnClickCounter() => DialogService.Show(new DialogOption()
|
||||
{
|
||||
Title = "自带的 Counter 组件",
|
||||
KeepChildrenState = KeepState,
|
||||
Component = DynamicComponent.CreateComponent<Counter>()
|
||||
Component = BootstrapDynamicComponent.CreateComponent<Counter>()
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
@@ -110,9 +93,9 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
ShowFooter = false,
|
||||
BodyContext = DataPrimaryId
|
||||
};
|
||||
op.BodyTemplate = DynamicComponent.CreateComponent<DataDialogComponent>(new List<KeyValuePair<string, object>>
|
||||
op.BodyTemplate = BootstrapDynamicComponent.CreateComponent<DataDialogComponent>(new KeyValuePair<string, object?>[]
|
||||
{
|
||||
new KeyValuePair<string, object>(nameof(DataDialogComponent.OnClose), new Action(async () => await op.Dialog.Close()))
|
||||
new(nameof(DataDialogComponent.OnClose), new Action(async () => await op.Dialog.Close()))
|
||||
}).Render();
|
||||
|
||||
await DialogService.Show(op);
|
||||
@@ -124,7 +107,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
var result = await DialogService.ShowModal<ResultDialogDemo>(new ResultDialogOption()
|
||||
{
|
||||
Title = "带返回值模态弹出框",
|
||||
ComponentParamters = new KeyValuePair<string, object>[]
|
||||
ComponentParamters = new KeyValuePair<string, object?>[]
|
||||
{
|
||||
new(nameof(ResultDialogDemo.Value), DemoValue1),
|
||||
new(nameof(ResultDialogDemo.ValueChanged), EventCallback.Factory.Create<int>(this, v => DemoValue1 = v))
|
||||
@@ -142,10 +125,10 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
var result = await DialogService.ShowModal<ResultDialogDemo2>(new ResultDialogOption()
|
||||
{
|
||||
Title = "选择收件人",
|
||||
BodyContext = 10,
|
||||
BodyContext = new ResultDialogDemo2.FooContext() { Count = 10, Emails = InputValue },
|
||||
ButtonYesText = "选择",
|
||||
ButtonYesIcon = "fa fa-search",
|
||||
ComponentParamters = new KeyValuePair<string, object>[]
|
||||
ComponentParamters = new KeyValuePair<string, object?>[]
|
||||
{
|
||||
// 用于初始化已选择的用户邮件
|
||||
new(nameof(ResultDialogDemo2.Emails), Emails),
|
||||
@@ -159,47 +142,12 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
}
|
||||
}
|
||||
|
||||
private int _counter;
|
||||
private async Task ShowDialogLoop()
|
||||
{
|
||||
await DialogService.Show(new DialogOption()
|
||||
{
|
||||
Title = $"弹窗 {_counter++}",
|
||||
Component = DynamicComponent.CreateComponent<Button>(new KeyValuePair<string, object>[]
|
||||
{
|
||||
new KeyValuePair<string, object>(nameof(Button.Text), $"点击弹窗 {DateTime.Now:HH:mm:ss}"),
|
||||
new KeyValuePair<string, object>(nameof(Button.OnClick), EventCallback.Factory.Create<MouseEventArgs>(this, async () => await ShowDialogLoop1()))
|
||||
}),
|
||||
OnCloseAsync = () =>
|
||||
{
|
||||
_counter--;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private async Task ShowDialogLoop1()
|
||||
{
|
||||
await DialogService.Show(new DialogOption()
|
||||
{
|
||||
Title = $"弹窗 {_counter++}",
|
||||
BodyTemplate = builder =>
|
||||
{
|
||||
builder.OpenElement(0, "div");
|
||||
builder.OpenComponent<Counter>(1);
|
||||
builder.CloseComponent();
|
||||
builder.AddContent(2, new MarkupString($"<div>当前时间 {DateTime.Now:HH:mm:ss}</div>"));
|
||||
builder.OpenComponent<Button>(3);
|
||||
builder.AddAttribute(4, nameof(Button.Text), $"点击弹窗 {DateTime.Now:HH:mm:ss}");
|
||||
builder.AddAttribute(4, nameof(Button.OnClick), EventCallback.Factory.Create<MouseEventArgs>(this, async () => await ShowDialogLoop()));
|
||||
builder.CloseComponent();
|
||||
builder.CloseElement();
|
||||
},
|
||||
OnCloseAsync = () =>
|
||||
{
|
||||
_counter--;
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
Title = $"弹窗 {DateTime.Now}",
|
||||
Component = BootstrapDynamicComponent.CreateComponent<DialogDemo>()
|
||||
});
|
||||
}
|
||||
|
||||
@@ -239,13 +187,6 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "KeepChildrenState",
|
||||
Description = "是否保持弹窗内组件状态",
|
||||
Type = "boolean",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "IsCentered",
|
||||
Description = "是否垂直居中",
|
||||
|
||||
128
src/BootstrapBlazor.Shared/Pages/Samples/Displays.razor
Normal file
@@ -0,0 +1,128 @@
|
||||
@page "/displays"
|
||||
|
||||
<h3>Display 显示组件</h3>
|
||||
|
||||
<h4>显示静态文本数据</h4>
|
||||
|
||||
<Block Title="基础用法" Introduction="仅显示">
|
||||
<div class="row">
|
||||
<div class="col-auto col-form-label">
|
||||
<span>基本用法</span>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<Display TValue="string" Value="@Model.Name" />
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="双向绑定数据" Introduction="通过双向绑定可以自动获取资源文件中的显示标签">
|
||||
<p><code>Display</code> 组件开启双向绑定时,会根据绑定的 <code>Model</code> 属性值去自动获取 <code>Display/DisplayName</code> 标签值并且显示为前置 <code>Label</code>,通过 <code>DisplayText</code> 属性可以自定义显示前置标签,或者通过 <code>ShowLabel</code> 属性关闭前置标签是否显示</p>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<Divider Text="自定义标签" />
|
||||
<div class="form-group col-12">
|
||||
<p>设置 <code>DisplayText</code> 值为 <b>自定义标签</b></p>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<Display @bind-Value="@Model.Name" DisplayText="自定义标签" ShowLabel="true" />
|
||||
</div>
|
||||
<Divider Text="占位" />
|
||||
<div class="form-group col-12">
|
||||
<p>无论是否设置 <code>DisplayText</code> 值,当 <code>ShowLabel</code> 为 <code>true</code> 时均显示</p>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<Display @bind-Value="@Model.Name" ShowLabel="true" />
|
||||
</div>
|
||||
<Divider Text="不占位" />
|
||||
<div class="form-group col-12">
|
||||
<p>无论是否设置 <code>DisplayText</code> 值,当 <code>ShowLabel</code> 为 <code>false</code> 时均不显示</p>
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<Display @bind-Value="@Model.Name" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="泛型绑定" Introduction="<code>Display</code> 组件内置对 <code>枚举</code> <code>集合</code> <code>数组</code> 进行处理,如不符合条件时,请自定义格式化或者回调委托方法">
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Display FormatString="000" @bind-Value="@Model.Count" ShowLabel="true" DisplayText="整型" />
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Display @bind-Value="@Model.Education" ShowLabel="true" DisplayText="枚举" />
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Display @bind-Value="@Model.Hobby" ShowLabel="true" DisplayText="集合" />
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Display @bind-Value="@ByteArray" ShowLabel="true" DisplayText="数组" />
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Display Value="@DateTime.Now" ShowLabel="true" DisplayText="DateTime" />
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Display Value="@DateTimeOffset.Now" ShowLabel="true" DisplayText="DateTimeOffset" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="表单内使用" Introduction="<code>Display</code> 组件在表单组件 <code>EditorForm</code> 中使用,多用于明细页,不可编辑模式">
|
||||
<p><b><code>form-inline form-group</code></b> 模式</p>
|
||||
<EditorForm Model="@Model" ItemsPerRow="3" IsDisplay="true">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@Model.Hobby" Data="@Hobbys" />
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
|
||||
<p><b><code>form-inline</code></b> 模式</p>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6"><Display @bind-Value="@Model.Count" ShowLabel="true" DisplayText="整型" /></div>
|
||||
<div class="col-12 col-sm-6"><Display @bind-Value="@Model.Education" ShowLabel="true" DisplayText="枚举" /></div>
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="自定义格式" Introduction="设置 <code>FormatString</code> 属性值为 <code>yyyy-MM-dd</code> 时,组件显示的时间格式为年月日">
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">设置 <code class="ml-1">FormatString</code></div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Display Value="DateTime.Now" FormatString="yyyy-MM-dd" />
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">设置 <code class="ml-1">Formatter</code></div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Display Value="DateTime.Now" FormatterAsync="@DateTimeFormatter" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p class="mt-3"><code>Display</code> 组件绑定 <code>byte[]</code> 数组,格式化成 <code>base64</code> 编码字符串示例</p>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">设置 <code class="ml-1">Formatter</code></div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Display Value="@ByteArray" FormatterAsync="@ByteArrayFormatter" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="自动翻译为 Text" Introduction="设置 <code>Data</code> 值为 <code>IEnumerable<SelectedItem></code> 集合,组件将通过此数据集,进行通过 <code>Value</code> 显示 <code>Text</code> 翻译工作">
|
||||
<p>
|
||||
<div>本例中组件 <code>Value="@@IntValue"</code> 设置 <code>Data="@@IntValueSource"</code> 组件将 <code>Value</code> 值对应的 <code>Text</code> 显示出来</div>
|
||||
<div><b>InitValue</b>: 1,2,3</div>
|
||||
<div><b>IntValueSource</b>: Text1,Text2,Text3</div>
|
||||
</p>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="col-12 col-sm-6">
|
||||
<Display Value="@IntValue" Data="@IntValueSource" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" />
|
||||
96
src/BootstrapBlazor.Shared/Pages/Samples/Displays.razor.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using BootstrapBlazor.Shared.Common;
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// Display 组件示例
|
||||
/// </summary>
|
||||
public partial class Displays
|
||||
{
|
||||
[NotNull]
|
||||
private Foo? Model { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IStringLocalizer<Foo>? Localizer { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private IEnumerable<SelectedItem>? Hobbys { get; set; }
|
||||
|
||||
private byte[] ByteArray { get; set; } = new byte[] { 0x01, 0x12, 0x34, 0x56 };
|
||||
|
||||
private IEnumerable<int> IntValue { get; set; } = new[] { 1, 2, 3 };
|
||||
|
||||
private IEnumerable<SelectedItem> IntValueSource { get; set; } = new[]
|
||||
{
|
||||
new SelectedItem("1", "Text1"),
|
||||
new SelectedItem("2", "Text2"),
|
||||
new SelectedItem("3", "Text3")
|
||||
};
|
||||
|
||||
private static async Task<string> ByteArrayFormatter(byte[] source)
|
||||
{
|
||||
await Task.Delay(10);
|
||||
return Convert.ToBase64String(source);
|
||||
}
|
||||
|
||||
private static Task<string> DateTimeFormatter(DateTime source) => Task.FromResult(source.ToString("yyyy-MM-dd"));
|
||||
|
||||
/// <summary>
|
||||
/// OnInitialized 方法
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
Model = Foo.Generate(Localizer);
|
||||
Model.Hobby = Foo.GenerateHobbys(Localizer).Take(3).Select(i => i.Text);
|
||||
Hobbys = Foo.GenerateHobbys(Localizer);
|
||||
}
|
||||
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new[]
|
||||
{
|
||||
new AttributeItem() {
|
||||
Name = "ShowLabel",
|
||||
Description = "是否显示前置标签",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "DisplayText",
|
||||
Description = "前置标签显示文本",
|
||||
Type = "string",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "FormatString",
|
||||
Description = "数值格式化字符串",
|
||||
Type = "string",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "Formatter",
|
||||
Description = "TableHeader 实例",
|
||||
Type = "RenderFragment<TItem>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
57
src/BootstrapBlazor.Shared/Pages/Samples/Downloads.razor
Normal file
@@ -0,0 +1,57 @@
|
||||
@page "/downloads"
|
||||
|
||||
<h3>Download 文件下载</h3>
|
||||
|
||||
<h4>用于直接下载物理文件</h4>
|
||||
|
||||
<Tips>
|
||||
<p>
|
||||
本组件使用注入服务的形式提供功能,使用时用户体验效果非常舒适,随时随地的调用,需要在使用本组件的页面中内置 <code>Download</code> 组件,或者在 <code>MainLayout</code> 主布局组件中内置,示例代码如下:
|
||||
</p>
|
||||
</Tips>
|
||||
|
||||
<Pre><Download /></Pre>
|
||||
|
||||
<Block Title="基本用法" Introduction="调用注入服务 <code>DownloadService</code>">
|
||||
<p>
|
||||
<b>特别注意:</b>
|
||||
<div>
|
||||
<code>Blazor</code> 与 <code>js</code> 的交互使用了 <code>json</code>,在 <code>ssr</code> 模式中,<code>json</code> 最大传输大小是 <b>125M</b>,这是 <code>asp.net core</code> 的限制。并且由于 <code>json</code> 转 <code>js</code> 的 <code>blob</code> 非常非常慢,所以大文件请谨慎,建议只在类似页面文件导出、报表图片下载等页面自行完成的内容中使用。
|
||||
其他例如服务器文件下载等依旧使用 <code>Controller</code> 来完成。如果下载大文件请自行仔细测试
|
||||
</div>
|
||||
</p>
|
||||
<div class="mb-3">
|
||||
示例:
|
||||
<Button Icon="fa fa-download" Text="下载文件" OnClick="@DownloadFileAsync"></Button>
|
||||
</div>
|
||||
<div><code>Razor</code> 代码</div>
|
||||
<Pre><Button OnClick="DownloadFile">点我下载文件</Button></Pre>
|
||||
<div><code>C#</code> 代码</div>
|
||||
<Pre>private async Task DownloadFileAsync()
|
||||
{
|
||||
var content = await GenerateFileAsync();
|
||||
await downloadService.DownloadAsync("测试文件", content);
|
||||
|
||||
static async Task<byte[]> GenerateFileAsync()
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
using var writer = new StreamWriter(ms);
|
||||
await writer.WriteLineAsync("自行生成并写入的文本,这里可以换成图片或其他内容");
|
||||
await writer.FlushAsync();
|
||||
ms.Position = 0;
|
||||
return ms.ToArray();
|
||||
}
|
||||
}</Pre>
|
||||
</Block>
|
||||
|
||||
<Block Title="大文件下载测试" Introduction="这里模拟生成了一个 <code>100万行</code> 的文本文件,大概 <b>56M</b>,可以自行测试">
|
||||
<p>按钮设置 <code>IsAsync</code> 值为 <code>true</code> 进行异步下载操作</p>
|
||||
<Button IsAsync="true" Icon="fa fa-download" Text="大文件下载" OnClickWithoutRender="DownloadLargeFileAsync"></Button>
|
||||
</Block>
|
||||
|
||||
<Block Title="获取图片并显示" Introduction="模拟直接由前端页面生成验证码或者上传图片不保存直接显示的情况。">
|
||||
<p>由于测试使用了wwwroot下的文件,没有代码生成,wasm无法访问wwwroot文件夹,故此测试只有ssr模式可用。wasm请自行测试。</p>
|
||||
<img src="@TempUrl" style="width: 120px; height: auto;" />
|
||||
</Block>
|
||||
|
||||
<Download></Download>
|
||||
93
src/BootstrapBlazor.Shared/Pages/Samples/Downloads.razor.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Options;
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
/// <summary>
|
||||
/// Title 网站标题示例代码
|
||||
/// </summary>
|
||||
public partial class Downloads
|
||||
{
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private ToastService? ToastService { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private DownloadService? downloadService { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IOptions<WebsiteOptions>? SiteOptions { get; set; }
|
||||
|
||||
private string? TempUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 渲染完成事件
|
||||
/// </summary>
|
||||
/// <param name="firstRender"></param>
|
||||
/// <returns></returns>
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
if (firstRender)
|
||||
{
|
||||
if (OperatingSystem.IsBrowser())
|
||||
{
|
||||
await ToastService.Information("显示图片", "当前模式为 WebAssembly 模式,无法直接调用 wwwroot 文件夹,请自行生成图片测试。");
|
||||
}
|
||||
else
|
||||
{
|
||||
var filePath = Path.Combine(SiteOptions.Value.WebRootPath, "favicon.png");
|
||||
TempUrl = await downloadService.CreateUrlAsync("favicon.png", File.OpenRead(filePath),
|
||||
"image/jpeg");
|
||||
StateHasChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task DownloadFileAsync()
|
||||
{
|
||||
var content = await GenerateFileAsync();
|
||||
await downloadService.DownloadAsync("测试文件.txt", content);
|
||||
|
||||
static async Task<byte[]> GenerateFileAsync()
|
||||
{
|
||||
using var ms = new MemoryStream();
|
||||
using var writer = new StreamWriter(ms);
|
||||
await writer.WriteLineAsync("自行生成并写入的文本,这里可以换成图片或其他内容");
|
||||
await writer.FlushAsync();
|
||||
ms.Position = 0;
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private Task DownloadLargeFileAsync() => Task.Run(async () =>
|
||||
{
|
||||
using var stream = await GenerateFileStreamAsync();
|
||||
await downloadService.DownloadAsync("测试大文件.txt", stream);
|
||||
|
||||
static async Task<Stream> GenerateFileStreamAsync()
|
||||
{
|
||||
var ms = new MemoryStream();
|
||||
var writer = new StreamWriter(ms);
|
||||
for (var i = 0; i < 1000; i++)
|
||||
{
|
||||
await writer.WriteLineAsync($"这里是一个大文件下载示例,共循环100万次");
|
||||
}
|
||||
await writer.FlushAsync();
|
||||
ms.Position = 0;
|
||||
return ms;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -22,11 +22,8 @@
|
||||
<EditorItem @bind-Field="@Model.Complete" Editable="false" />
|
||||
<EditorItem @bind-Field="@Model.Hobby">
|
||||
<EditTemplate Context="value">
|
||||
@{
|
||||
var model = value as Foo;
|
||||
}
|
||||
<div class="form-group col-12">
|
||||
<CheckboxList @bind-Value="@model!.Hobby" Items="@Hobbys" />
|
||||
<CheckboxList @bind-Value="@Model.Hobby" Items="@Hobbys" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
@@ -45,21 +42,11 @@
|
||||
<ValidateForm Model="@ValidateModel">
|
||||
<EditorForm TModel="Foo">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@Model.DateTime" Readonly="true" />
|
||||
<EditorItem @bind-Field="@Model.Hobby">
|
||||
<EditorItem @bind-Field="@ValidateModel.DateTime" Readonly="true" />
|
||||
<EditorItem @bind-Field="@ValidateModel.Hobby">
|
||||
<EditTemplate Context="value">
|
||||
@{
|
||||
var model = value as Foo;
|
||||
}
|
||||
<div class="form-group col-12">
|
||||
<CheckboxList @bind-Value="@model!.Hobby" Items="@Hobbys" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
<EditorItem @bind-Field="@Model.Complete">
|
||||
<EditTemplate Context="value">
|
||||
<div class="form-group col-6">
|
||||
<Switch @bind-Value="((Foo)value).Complete" />
|
||||
<CheckboxList @bind-Value="@ValidateModel.Hobby" Items="@Hobbys" />
|
||||
</div>
|
||||
</EditTemplate>
|
||||
</EditorItem>
|
||||
@@ -121,7 +108,7 @@
|
||||
<EditorItem @bind-Field="@Model.Hobby" Data="@Hobbys" />
|
||||
</FieldItems>
|
||||
<Buttons>
|
||||
<Button Icon="fa fa-save" Text="提交" />
|
||||
<Button ButtonType="ButtonType.Submit" Icon="fa fa-save" Text="提交" />
|
||||
</Buttons>
|
||||
</EditorForm>
|
||||
</ValidateForm>
|
||||
|
||||
@@ -114,17 +114,17 @@
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<div class="demo-inputnumber">
|
||||
<BootstrapInputNumber Value="10" Color="Color.Danger" />
|
||||
<BootstrapInputNumber Value="@BindFloatValue" Color="Color.Danger" FormatString="#.##" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<div class="demo-inputnumber">
|
||||
<BootstrapInputNumber Value="10" Color="Color.Dark" />
|
||||
<BootstrapInputNumber Value="@BindDoubleValue" Color="Color.Dark" FormatString="#.##" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<div class="demo-inputnumber">
|
||||
<BootstrapInputNumber Value="10" Color="Color.Secondary" />
|
||||
<BootstrapInputNumber Value="@BindDecimalValue" Color="Color.Secondary" FormatString="#.##" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -139,16 +139,6 @@
|
||||
<BootstrapInputNumber Value="@BindShortValue" DisplayText="Short" ShowLabel="true" ShowButton="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<div class="demo-inputnumber">
|
||||
<BootstrapInputNumber Value="@BindLongValue" DisplayText="Long" ShowLabel="true" ShowButton="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<div class="demo-inputnumber">
|
||||
<BootstrapInputNumber Value="@BindFloatValue" DisplayText="Float" ShowLabel="true" ShowButton="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<div class="demo-inputnumber">
|
||||
<BootstrapInputNumber Value="@BindValue" DisplayText="Int" ShowLabel="true" ShowButton="true" />
|
||||
@@ -156,12 +146,22 @@
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<div class="demo-inputnumber">
|
||||
<BootstrapInputNumber Value="@BindDoubleValue" DisplayText="Double" ShowLabel="true" ShowButton="true" />
|
||||
<BootstrapInputNumber Value="@BindLongValue" DisplayText="Long" ShowLabel="true" ShowButton="true" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<div class="demo-inputnumber">
|
||||
<BootstrapInputNumber Value="@BindDecimalValue" DisplayText="Decimal" ShowLabel="true" ShowButton="true" />
|
||||
<BootstrapInputNumber Value="@BindFloatValue" DisplayText="Float" ShowLabel="true" ShowButton="true" FormatString="#.##" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<div class="demo-inputnumber">
|
||||
<BootstrapInputNumber Value="@BindDoubleValue" DisplayText="Double" ShowLabel="true" ShowButton="true" FormatString="#.##" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<div class="demo-inputnumber">
|
||||
<BootstrapInputNumber Value="@BindDecimalValue" DisplayText="Decimal" ShowLabel="true" ShowButton="true" FormatString="#.##" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
|
||||
<Block Title="双向绑定数据" Introduction="绑定组件内变量,数据自动同步">
|
||||
<p><code>BootstrapInput</code> 组件开启双向绑定时,会根据绑定的 <code>Model</code> 属性值去自动获取 <code>Display/DisplayName</code> 标签值并且显示为前置 <code>Label</code>,通过 <code>DisplayText</code> 属性可以自定义显示前置标签,或者通过 <code>ShowLabel</code> 属性关闭前置标签是否显示</p>
|
||||
<Tips>特别注意:所有表单组件如果内置到 <code>EditForm</code> 中使用时,即使 <code>ShowLabel</code> 设置为 <code>false</code> 也是会显示前置标签</Tips>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<Divider Text="自定义标签" />
|
||||
|
||||
@@ -34,62 +34,59 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
PlaceHolderText = Localizer["PlaceHolder"];
|
||||
}
|
||||
|
||||
private static IEnumerable<AttributeItem> GetAttributes()
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new[]
|
||||
{
|
||||
return new AttributeItem[]
|
||||
new AttributeItem() {
|
||||
Name = "ChildContent",
|
||||
Description = "验证控件",
|
||||
Type = "RenderFragment",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "ShowLabel",
|
||||
Description = "是否显示前置标签",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "DisplayText",
|
||||
Description = "前置标签显示文本",
|
||||
Type = "string",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "FormatString",
|
||||
Description = "数值格式化字符串",
|
||||
Type = "string",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "Formatter",
|
||||
Description = "TableHeader 实例",
|
||||
Type = "RenderFragment<TItem>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem()
|
||||
{
|
||||
new AttributeItem() {
|
||||
Name = "ChildContent",
|
||||
Description = "验证控件",
|
||||
Type = "RenderFragment",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "ShowLabel",
|
||||
Description = "是否显示前置标签",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "DisplayText",
|
||||
Description = "前置标签显示文本",
|
||||
Type = "string",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "FormatString",
|
||||
Description = "数值格式化字符串",
|
||||
Type = "string",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "Formatter",
|
||||
Description = "TableHeader 实例",
|
||||
Type = "RenderFragment<TItem>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem()
|
||||
{
|
||||
Name = "type",
|
||||
Description = "控件类型",
|
||||
Type = "string",
|
||||
ValueList = "text / number / email / url / password",
|
||||
DefaultValue = "text"
|
||||
},
|
||||
new AttributeItem()
|
||||
{
|
||||
Name = "IsDisabled",
|
||||
Description = "是否禁用 默认为 fasle",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
}
|
||||
};
|
||||
}
|
||||
Name = "type",
|
||||
Description = "控件类型",
|
||||
Type = "string",
|
||||
ValueList = "text / number / email / url / password",
|
||||
DefaultValue = "text"
|
||||
},
|
||||
new AttributeItem()
|
||||
{
|
||||
Name = "IsDisabled",
|
||||
Description = "是否禁用 默认为 fasle",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
152
src/BootstrapBlazor.Shared/Pages/Samples/Labels.razor
Normal file
@@ -0,0 +1,152 @@
|
||||
@layout ComponentLayout
|
||||
@page "/labels"
|
||||
|
||||
<h3>组件标签</h3>
|
||||
|
||||
<p>本套组件中有 <code>ValidateForm</code> <code>EditorForm</code> 以及多种继承 <code>ValidateBase<TValue></code> 的 <b>表单组件</b>,这些组件中有一套特殊的显示前置标签逻辑,现在我们统一的梳理一下:</p>
|
||||
|
||||
<ul class="ul-demo">
|
||||
<li><a href="/validateforms" target="_blank">ValidateForm</a> 组件是 <b>可验证的</b> 表单组件,此组件内的表单组件会自动进行数据合规性检查,如果数据不合规将会阻止 <b>提交(Submit)</b> 动作,是数据提交中使用最最最频繁的组件</li>
|
||||
<li><a href="/editorforms" target="_blank">EditorForm</a> 组件是普通的表单组件,此组件绑定 <code>Model</code> 后即可自动生成整个表单,大大减少重复性编码,外面套上 <code>ValidateForm</code> 即可开启 <b>数据合规性检查</b> 非常方便、简洁、高效</li>
|
||||
</ul>
|
||||
|
||||
<p>以 <a href="/inputs" target="_blank">BootstrapInput</a> 输入框组件为例,阐述一下是否显示 <code>Label</code> 逻辑</p>
|
||||
|
||||
<Tips>
|
||||
<p><code>ShowLabel</code> 的逻辑即就近原则,离自身越近的设置生效,如表单组件内置到 <code>ValidateForm</code> 组件中,即使 <code>ValidateForm</code> 设置 <code>ShowLabel=true</code>,表单组件自身设置 <code>ShowLabel=false</code> 时,标签最终结果为 <b>不显示</b></p>
|
||||
</Tips>
|
||||
|
||||
<Block Title="单独使用" Introduction="适用于数据录入">
|
||||
<p><b>未使用双向绑定时</b></p>
|
||||
<ul class="ul-demo">
|
||||
<li>默认不会显示 <code>Label</code></li>
|
||||
<li>通过 <code>ShowLabel</code> 属性进行控制是否显示</li>
|
||||
<li>设置 <code>DisplayText</code> 时显示内容</li>
|
||||
<li>未设置时渲染一个无内容的 <code>label</code> 组件进行占位</li>
|
||||
</ul>
|
||||
|
||||
<GroupBox Title="未双向绑定" style="margin-top: 1.5rem;">
|
||||
<div>第一个文本框未进行任何设置,不显示标签</div>
|
||||
<div>第二个文本框设置 <code>ShowLabel="true" DisplayText=""</code> 显示无内容的占位标签</div>
|
||||
<div>第三个文本框设置 <code>ShowLabel="true" DisplayText="Name"</code> 显示设置的内容标签</div>
|
||||
<div>第四个文本框设置 <code>ShowLabel="true" DisplayText="@@null"</code> 显示无内容的占位标签</div>
|
||||
<div class="form-inline mt-3">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-sm-12 col-md-3">
|
||||
<BootstrapInput TValue="string" />
|
||||
</div>
|
||||
<div class="form-group col-sm-12 col-md-3">
|
||||
<BootstrapInput TValue="string" ShowLabel="true" DisplayText="" />
|
||||
</div>
|
||||
<div class="form-group col-sm-12 col-md-3">
|
||||
<BootstrapInput TValue="string" ShowLabel="true" DisplayText="@Localizer[nameof(Foo.Name)]" />
|
||||
</div>
|
||||
<div class="form-group col-sm-12 col-md-3">
|
||||
<BootstrapInput TValue="string" ShowLabel="true" DisplayText="@null" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</GroupBox>
|
||||
|
||||
<p class="mt-3"><b>使用双向绑定时</b></p>
|
||||
<GroupBox Title="双向绑定" class="mt-3">
|
||||
<div>第一个文本框设置 <code>@@bind-Value="@@Dummy.Name"</code>,不显示标签</div>
|
||||
<div>第二个文本框设置 <code>@@bind-Value="@@Dummy.Name" ShowLabel="true" DisplayText="@@Localizer[nameof(Foo.Address)]"</code> 显示设置的内容</div>
|
||||
<div>第三个文本框设置 <code>@@bind-Value="@@Dummy.Name" ShowLabel="true" DisplayText=""</code> 显示无内容占位标签</div>
|
||||
<div>第四个文本框设置 <code>@@bind-Value="@@Dummy.Name" ShowLabel="true" DisplayText="@@null"</code> 显示资源文件机制下的标签内容 <code>Label</code></div>
|
||||
<div class="form-inline mt-3">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-sm-12 col-md-3">
|
||||
<BootstrapInput @bind-Value="@Dummy.Name" />
|
||||
</div>
|
||||
<div class="form-group col-sm-12 col-md-3">
|
||||
<BootstrapInput @bind-Value="@Dummy.Name" ShowLabel="true" DisplayText="@Localizer[nameof(Foo.Address)]" />
|
||||
</div>
|
||||
<div class="form-group col-sm-12 col-md-3">
|
||||
<BootstrapInput @bind-Value="@Dummy.Name" ShowLabel="true" DisplayText="" />
|
||||
</div>
|
||||
<div class="form-group col-sm-12 col-md-3">
|
||||
<BootstrapInput @bind-Value="@Dummy.Name" ShowLabel="true" DisplayText="@null" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</GroupBox>
|
||||
</Block>
|
||||
|
||||
<Block Title="EditorForm 中使用" , Introduction="未套 <code>ValidateForm</code> 中使用">
|
||||
<p><b>显示标签</b><div>未设置 <coe>EditorForm</coe> 组件的 <code>ShowLabel</code> 属性,未设置时等同于设置为 <code>true</code>,所有组件 <b>显示</b> 标签</div></p>
|
||||
<GroupBox>
|
||||
<EditorForm Model="@Dummy">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.Hobby" Data="@Foo.GenerateHobbys(Localizer)">
|
||||
</EditorItem>
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
</GroupBox>
|
||||
|
||||
<p class="mt-3"><b>不显示标签</b><div>设置 <code>ShowLabel="false"</code>,组件内的所有表单组件 <b>不显示</b> 标签</div></p>
|
||||
<GroupBox>
|
||||
<EditorForm Model="@Dummy" ShowLabel="false">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.Hobby" Data="@Foo.GenerateHobbys(Localizer)">
|
||||
</EditorItem>
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
</GroupBox>
|
||||
</Block>
|
||||
|
||||
<Block Title="EditorForm 内置 ValidateForm 中使用" , Introduction="外置 <code>ValidateForm</code> 中使用">
|
||||
<p><b>显示标签</b><div>未设置 <coe>EditorForm</coe> 组件的 <code>ShowLabel</code> 属性,未设置时等同于设置为 <code>true</code>,所有组件 <b>显示</b> 标签</div></p>
|
||||
<GroupBox>
|
||||
<ValidateForm Model="@Dummy">
|
||||
<EditorForm TModel="Foo">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.Hobby" Data="@Foo.GenerateHobbys(Localizer)">
|
||||
</EditorItem>
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
</ValidateForm>
|
||||
</GroupBox>
|
||||
|
||||
<p class="mt-3"><b>不显示标签</b><div>设置 <code>ShowLabel="false"</code>,组件内的所有表单组件 <b>不显示</b> 标签</div></p>
|
||||
<GroupBox>
|
||||
<ValidateForm Model="@Dummy" ShowLabel="false">
|
||||
<EditorForm TModel="Foo">
|
||||
<FieldItems>
|
||||
<EditorItem @bind-Field="@context.Hobby" Data="@Foo.GenerateHobbys(Localizer)">
|
||||
</EditorItem>
|
||||
</FieldItems>
|
||||
</EditorForm>
|
||||
</ValidateForm>
|
||||
</GroupBox>
|
||||
</Block>
|
||||
|
||||
<Block Title="ValidateForm 中使用" , Introduction="默认自动开启显示标签">
|
||||
<p><b>显示标签</b><div>未设置 <coe>EditorForm</coe> 组件的 <code>ShowLabel</code> 属性,未设置时等同于设置为 <code>true</code>,所有组件 <b>显示</b> 标签</div></p>
|
||||
<GroupBox>
|
||||
<ValidateForm Model="@Dummy" class="form-inline">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-sm-12 col-md-6">
|
||||
<BootstrapInput @bind-Value="@Dummy.Name" />
|
||||
</div>
|
||||
<div class="form-group col-sm-12 col-md-6">
|
||||
<BootstrapInput @bind-Value="@Dummy.Address" />
|
||||
</div>
|
||||
</div>
|
||||
</ValidateForm>
|
||||
</GroupBox>
|
||||
|
||||
<p class="mt-3"><b>不显示标签</b><div>设置 <code>ShowLabel="false"</code>,组件内的所有表单组件 <b>不显示</b> 标签</div></p>
|
||||
<GroupBox>
|
||||
<ValidateForm Model="@Dummy" ShowLabel="false" class="form-inline">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-sm-12 col-md-6">
|
||||
<BootstrapInput @bind-Value="@Dummy.Name" />
|
||||
</div>
|
||||
<div class="form-group col-sm-12 col-md-6">
|
||||
<BootstrapInput @bind-Value="@Dummy.Address" />
|
||||
</div>
|
||||
</div>
|
||||
</ValidateForm>
|
||||
</GroupBox>
|
||||
</Block>
|
||||
34
src/BootstrapBlazor.Shared/Pages/Samples/Labels.razor.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public partial class Labels : ComponentBase
|
||||
{
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IStringLocalizer<Foo>? Localizer { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private Foo? Dummy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// OnInitialized 方法
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
Dummy = Foo.Generate(Localizer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// <returns></returns>
|
||||
public async Task UpdateAsync()
|
||||
{
|
||||
await RootPage.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>()
|
||||
await RootPage.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object?>()
|
||||
{
|
||||
[nameof(RootPage.IsFullSide)] = IsFullSide,
|
||||
[nameof(RootPage.IsFixedFooter)] = IsFixedFooter && ShowFooter,
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
</Header>
|
||||
<Side>
|
||||
<div style="position: absolute; top: 0; left:0; right: 0; bottom: 0; overflow: auto; border-right: 1px solid rgba(0,0,0,.125); padding: 6px 0;">
|
||||
<Menu Items="@GetIconSideMenuItems()" IsVertical="true"></Menu>
|
||||
<Menu Items="@IconSideMenuItems" DisableNavigation="true" IsVertical="true"></Menu>
|
||||
</div>
|
||||
</Side>
|
||||
<Main>
|
||||
@@ -146,7 +146,7 @@
|
||||
</Header>
|
||||
<Side>
|
||||
<div style="border-right: 1px solid rgba(0,0,0,.125); padding: 6px 0;">
|
||||
<Menu Items="@GetIconSideMenuItems()" IsVertical="true"></Menu>
|
||||
<Menu Items="@IconSideMenuItems" DisableNavigation="true" IsVertical="true"></Menu>
|
||||
</div>
|
||||
</Side>
|
||||
<Main>
|
||||
|
||||
@@ -4,7 +4,12 @@
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using BootstrapBlazor.Shared.Common;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
using static BootstrapBlazor.Shared.Pages.Menus;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
@@ -13,31 +18,24 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// </summary>
|
||||
public sealed partial class Layouts
|
||||
{
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IStringLocalizer<Menus>? Localizer { get; set; }
|
||||
|
||||
private IEnumerable<MenuItem> GetIconSideMenuItems()
|
||||
private IEnumerable<MenuItem>? IconSideMenuItems { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// OnInitializedAsync 方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var ret = new List<MenuItem>
|
||||
{
|
||||
new MenuItem() { Text = "系统设置", IsActive = true, Icon = "fa fa-fw fa-gears" },
|
||||
new MenuItem() { Text = "权限设置", Icon = "fa fa-fw fa-users" },
|
||||
new MenuItem() { Text = "日志设置", Icon = "fa fa-fw fa-database" }
|
||||
};
|
||||
await base.OnInitializedAsync();
|
||||
|
||||
ret[0].AddItem(new MenuItem() { Text = "网站设置", Icon = "fa fa-fw fa-fa" });
|
||||
ret[0].AddItem(new MenuItem() { Text = "任务设置", Icon = "fa fa-fw fa-tasks" });
|
||||
|
||||
ret[1].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });
|
||||
|
||||
ret[2].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
|
||||
ret[2].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
|
||||
ret[2].AddItem(new MenuItem() { Text = "操作日志", Icon = "fa fa-fw fa-edit" });
|
||||
|
||||
return ret;
|
||||
IconSideMenuItems = await MenusDataGerator.GetIconSideMenuItemsAsync(Localizer);
|
||||
}
|
||||
|
||||
private IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
{
|
||||
// TODO: 移动到数据库中
|
||||
new AttributeItem() {
|
||||
|
||||
@@ -57,4 +57,9 @@
|
||||
<Markdown Height="500" MinHeight="300" Placeholder="这是 Markdown" PreviewStyle="PreviewStyle.Tab" InitialEditType="InitialEditType.Wysiwyg" Language="@Language"></Markdown>
|
||||
</Block>
|
||||
|
||||
<Block Title="浏览器模式" Introduction="单纯浏览模式,不可编辑">
|
||||
<p>设置<code>Markdown</code> 编辑器为纯浏览模式,<code>IsViewer="true"</code></p>
|
||||
<Markdown IsViewer="true" Value="# Viewer Mode"></Markdown>
|
||||
</Block>
|
||||
|
||||
<AttributeTable Items="GetAttributes()"></AttributeTable>
|
||||
|
||||
@@ -18,8 +18,6 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
|
||||
private string? HtmlString { get; set; }
|
||||
|
||||
private string ShowHideButtonString { get; set; } = "隐藏 Editor";
|
||||
|
||||
/// <summary>
|
||||
/// 获得/设置 版本号字符串
|
||||
/// </summary>
|
||||
@@ -81,6 +79,13 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
Type = "string",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem(){
|
||||
Name = "IsViewer",
|
||||
Description = "是否为纯浏览模式",
|
||||
Type = "bool",
|
||||
ValueList = " true/false ",
|
||||
DefaultValue = " false "
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@
|
||||
</Block>
|
||||
|
||||
<Block Title="侧栏" Introduction="适用于左右结构布局的网站,通过设置 <code>IsVertical</code> 更改导航菜单为侧栏">
|
||||
<div style="width:220px;">
|
||||
<Menu Items="@SideMenuItems" DisableNavigation="true" IsVertical="true" OnClick="@OnClickSideMenu" style="border-right: 1px solid #e6e6e6;" />
|
||||
<div style="width:220px; border-right: 1px solid #e6e6e6; padding-right: 4px;">
|
||||
<Menu Items="@SideMenuItems" DisableNavigation="true" IsVertical="true" OnClick="@OnClickSideMenu" />
|
||||
</div>
|
||||
<Logger @ref="TraceSideMenu" class="mt-3" />
|
||||
</Block>
|
||||
@@ -51,7 +51,7 @@
|
||||
</Header>
|
||||
<Side>
|
||||
<div class="menu-demo" style="background-color: #2f4050; color: #dcdfe6; height: 100%; padding: 6px 0;">
|
||||
<Menu Items="@IconSideMenuItems" IsVertical="true" IsCollapsed="@IsCollapsed" />
|
||||
<Menu Items="@IconSideMenuItems" DisableNavigation="true" IsVertical="true" IsCollapsed="@IsCollapsed" />
|
||||
</div>
|
||||
</Side>
|
||||
<Main>
|
||||
@@ -76,13 +76,22 @@
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="动态更改菜单" Introduction="通过代码动态设置 <code>Items</code> 属性值更改菜单项">
|
||||
<div class="mt-3" style="width:220px;">
|
||||
<Menu Items="@DynamicSideMenuItems" DisableNavigation="true" IsVertical="true" style="border-right: 1px solid #e6e6e6;" />
|
||||
</div>
|
||||
<Button Text="更新菜单" OnClick="UpdateMenu" />
|
||||
<Button Text="重置菜单" OnClick="ResetMenu" />
|
||||
</Block>
|
||||
|
||||
<Block Title="部分菜单禁用功能" Introduction="通过设置 <code>MenuItem</code> 的 <code>IsDisabled</code> 属性设置节点是否禁用">
|
||||
<p>本例中 <b>导航二</b> 节点为禁用状态,菜单与其子菜单均不可点击</p>
|
||||
<Menu Items="@DisabledMenuItems" />
|
||||
<Menu Items="@DisabledMenuItems" DisableNavigation="true" OnClick="@OnClick2" />
|
||||
<p class="mt-3"><b>侧栏的禁用示例</b></p>
|
||||
<div style="width:220px;">
|
||||
<Menu Items="@DisabledMenuItems" DisableNavigation="true" IsVertical="true" style="border-right: 1px solid #e6e6e6;" />
|
||||
<div style="width:220px; border-right: 1px solid #e6e6e6;">
|
||||
<Menu Items="@DisabledMenuItems" DisableNavigation="true" IsVertical="true" OnClick="@OnClick2" />
|
||||
</div>
|
||||
<Logger @ref="Trace2" class="mt-3" />
|
||||
</Block>
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" />
|
||||
|
||||
@@ -6,8 +6,9 @@ using BootstrapBlazor.Components;
|
||||
using BootstrapBlazor.Shared.Common;
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
@@ -17,21 +18,54 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// </summary>
|
||||
public sealed partial class Menus
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
private Logger? Trace { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private Logger? Trace2 { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private Logger? TraceSideMenu { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private IEnumerable<MenuItem>? Items { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private IEnumerable<MenuItem>? IconItems { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private IEnumerable<MenuItem>? SideMenuItems { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private IEnumerable<MenuItem>? IconSideMenuItems { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private IEnumerable<MenuItem>? WidgetIconSideMenuItems { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private IEnumerable<MenuItem>? CollapsedIconSideMenuItems { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private IEnumerable<MenuItem>? DisabledMenuItems { get; set; }
|
||||
|
||||
[NotNull]
|
||||
private IEnumerable<MenuItem>? DynamicSideMenuItems { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IStringLocalizer<Menus>? Localizer { get; set; }
|
||||
|
||||
private Task OnClickMenu(MenuItem item)
|
||||
{
|
||||
Trace?.Log($"菜单点击项: {item.Text}");
|
||||
Trace.Log($"菜单点击项: {item.Text}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
private Logger? TraceSideMenu { get; set; }
|
||||
private Task OnClick2(MenuItem item)
|
||||
{
|
||||
Trace2.Log($"菜单点击项: {item.Text}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task OnClickSideMenu(MenuItem item)
|
||||
{
|
||||
@@ -51,269 +85,344 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private IEnumerable<MenuItem> Items { get; set; } = Enumerable.Empty<MenuItem>();
|
||||
|
||||
private IEnumerable<MenuItem> GetItems()
|
||||
/// <summary>
|
||||
/// OnInitialized 方法
|
||||
/// </summary>
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
var ret = new List<MenuItem>
|
||||
{
|
||||
new MenuItem() { Text = "导航一" },
|
||||
new MenuItem() { Text = "导航二", IsActive = true },
|
||||
new MenuItem() { Text = "导航三" }
|
||||
};
|
||||
|
||||
ret[1].AddItem(new MenuItem() { Text = "子菜单一" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "子菜单二" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "子菜单三" });
|
||||
|
||||
ret[1].Items.ElementAt(0).AddItem(new MenuItem() { Text = "孙菜单1一" });
|
||||
ret[1].Items.ElementAt(0).AddItem(new MenuItem() { Text = "孙菜单1二" });
|
||||
|
||||
ret[1].Items.ElementAt(1).AddItem(new MenuItem() { Text = "孙菜单2一" });
|
||||
ret[1].Items.ElementAt(1).AddItem(new MenuItem() { Text = "孙菜单2二" });
|
||||
|
||||
ret[1].Items.ElementAt(1).Items.ElementAt(1).AddItem(new MenuItem() { Text = "曾孙菜单一" });
|
||||
ret[1].Items.ElementAt(1).Items.ElementAt(1).AddItem(new MenuItem() { Text = "曾孙菜单二" });
|
||||
|
||||
ret[1].Items.ElementAt(1).Items.ElementAt(1).Items.ElementAt(1).AddItem(new MenuItem() { Text = "曾曾孙菜单一" });
|
||||
ret[1].Items.ElementAt(1).Items.ElementAt(1).Items.ElementAt(1).AddItem(new MenuItem() { Text = "曾曾孙菜单二" });
|
||||
|
||||
return ret;
|
||||
await base.OnInitializedAsync();
|
||||
Items = await MenusDataGerator.GetTopItemsAsync(Localizer);
|
||||
IconItems = await MenusDataGerator.GetTopIconItemsAsync(Localizer);
|
||||
SideMenuItems = await MenusDataGerator.GetSideMenuItemsAsync(Localizer);
|
||||
IconSideMenuItems = await MenusDataGerator.GetIconSideMenuItemsAsync(Localizer);
|
||||
WidgetIconSideMenuItems = await MenusDataGerator.GetWidgetIconSideMenuItemsAsync(Localizer);
|
||||
CollapsedIconSideMenuItems = await MenusDataGerator.GetCollapsedIconSideMenuItemsAsync(Localizer);
|
||||
DisabledMenuItems = await MenusDataGerator.GetDisabledMenuItemsAsync(Localizer);
|
||||
DynamicSideMenuItems = await MenusDataGerator.GetSideMenuItemsAsync(Localizer);
|
||||
}
|
||||
|
||||
private IEnumerable<MenuItem> IconItems { get; set; } = Enumerable.Empty<MenuItem>();
|
||||
|
||||
private IEnumerable<MenuItem> GetIconItems()
|
||||
private async Task UpdateMenu()
|
||||
{
|
||||
var ret = new List<MenuItem>
|
||||
{
|
||||
new MenuItem() { Text = "导航一", Icon = "fa fa-life-bouy fa-fw" },
|
||||
new MenuItem() { Text = "导航二", Icon = "fa fa-fa fa-fw", IsActive = true },
|
||||
new MenuItem() { Text = "导航三", Icon = "fa fa-rebel fa-fw" }
|
||||
};
|
||||
|
||||
ret[1].AddItem(new MenuItem() { Text = "子菜单一", Icon = "fa fa-fa fa-fw" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "子菜单二", Icon = "fa fa-fa fa-fw" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "子菜单三", Icon = "fa fa-fa fa-fw" });
|
||||
|
||||
return ret;
|
||||
DynamicSideMenuItems = await MenusDataGerator.GetIconSideMenuItemsAsync(Localizer);
|
||||
}
|
||||
|
||||
private IEnumerable<MenuItem> SideMenuItems { get; set; } = Enumerable.Empty<MenuItem>();
|
||||
|
||||
private IEnumerable<MenuItem> GetSideMenuItems()
|
||||
private async Task ResetMenu()
|
||||
{
|
||||
var ret = new List<MenuItem>
|
||||
{
|
||||
new MenuItem() { Text = "导航一" },
|
||||
new MenuItem() { Text = "导航二" },
|
||||
new MenuItem() { Text = "导航三" },
|
||||
new MenuItem() { Text = "导航四" }
|
||||
};
|
||||
|
||||
ret[1].AddItem(new MenuItem() { Text = "子菜单一" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "子菜单二" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "子菜单三" });
|
||||
|
||||
ret[3].AddItem(new MenuItem() { Text = "子菜单一" });
|
||||
ret[3].AddItem(new MenuItem() { Text = "子菜单二" });
|
||||
ret[3].AddItem(new MenuItem() { Text = "子菜单三" });
|
||||
|
||||
ret[1].Items.ElementAt(0).AddItem(new MenuItem() { Text = "孙菜单1一" });
|
||||
ret[1].Items.ElementAt(0).AddItem(new MenuItem() { Text = "孙菜单1二" });
|
||||
|
||||
ret[1].Items.ElementAt(1).AddItem(new MenuItem() { Text = "孙菜单2一" });
|
||||
ret[1].Items.ElementAt(1).AddItem(new MenuItem() { Text = "孙菜单2二" });
|
||||
|
||||
ret[1].Items.ElementAt(0).Items.ElementAt(0).AddItem(new MenuItem() { Text = "曾孙菜单一" });
|
||||
ret[1].Items.ElementAt(0).Items.ElementAt(0).AddItem(new MenuItem() { Text = "曾孙菜单二" });
|
||||
|
||||
ret[1].Items.ElementAt(0).Items.ElementAt(0).Items.ElementAt(0).AddItem(new MenuItem() { Text = "曾曾孙菜单一" });
|
||||
ret[1].Items.ElementAt(0).Items.ElementAt(0).Items.ElementAt(0).AddItem(new MenuItem() { Text = "曾曾孙菜单二" });
|
||||
|
||||
return ret;
|
||||
DynamicSideMenuItems = await MenusDataGerator.GetSideMenuItemsAsync(Localizer);
|
||||
}
|
||||
|
||||
private IEnumerable<MenuItem> IconSideMenuItems { get; set; } = Enumerable.Empty<MenuItem>();
|
||||
|
||||
private IEnumerable<MenuItem> GetIconSideMenuItems()
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
{
|
||||
var ret = new List<MenuItem>
|
||||
new AttributeItem()
|
||||
{
|
||||
new MenuItem() { Text = "系统设置", IsActive = true, Icon = "fa fa-fw fa-gears" },
|
||||
new MenuItem() { Text = "权限设置", Icon = "fa fa-fw fa-users" },
|
||||
new MenuItem() { Text = "日志设置", Icon = "fa fa-fw fa-database" }
|
||||
};
|
||||
Name = "Items",
|
||||
Description = "菜单组件数据集合",
|
||||
Type = "IEnumerable<MenuItem>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem()
|
||||
{
|
||||
Name = "IsVertical",
|
||||
Description = "是否为侧栏",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "IsAccordion",
|
||||
Description = "是否手风琴效果",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "DisableNavigation",
|
||||
Description = "是否禁止地址栏导航",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "OnClick",
|
||||
Description = "菜单项被点击时回调此方法",
|
||||
Type = "Func<MenuItem, Task>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
}
|
||||
};
|
||||
|
||||
ret[0].AddItem(new MenuItem() { Text = "网站设置", Icon = "fa fa-fw fa-fa" });
|
||||
ret[0].AddItem(new MenuItem() { Text = "任务设置", Icon = "fa fa-fw fa-tasks" });
|
||||
|
||||
ret[1].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });
|
||||
|
||||
ret[2].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
|
||||
ret[2].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
|
||||
ret[2].AddItem(new MenuItem() { Text = "操作日志", Icon = "fa fa-fw fa-edit" });
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private DynamicComponent BuildDynamicComponent()
|
||||
internal static class MenusDataGerator
|
||||
{
|
||||
return DynamicComponent.CreateComponent<Badge>(new KeyValuePair<string, object>[]
|
||||
public static async Task<IEnumerable<MenuItem>> GetTopItemsAsync(IStringLocalizer localizer)
|
||||
{
|
||||
new KeyValuePair<string, object>(nameof(Badge.Color), Color.Danger),
|
||||
new KeyValuePair<string, object>(nameof(Badge.IsPill), true),
|
||||
new KeyValuePair<string, object>(nameof(Badge.ChildContent), new RenderFragment(builder =>
|
||||
await Task.Delay(1);
|
||||
|
||||
return new List<MenuItem>
|
||||
{
|
||||
new(localizer["Menu1"].Value),
|
||||
new(localizer["Menu2"].Value)
|
||||
{
|
||||
IsActive = true,
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu1"].Value)
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu11"].Value),
|
||||
new(localizer["SubMenu12"].Value)
|
||||
}
|
||||
},
|
||||
new(localizer["SubMenu2"].Value)
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu21"].Value),
|
||||
new(localizer["SubMenu22"].Value)
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu31"].Value),
|
||||
new(localizer["SubMenu32"].Value)
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu41"].Value),
|
||||
new(localizer["SubMenu42"].Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new(localizer["SubMenu3"].Value)
|
||||
}
|
||||
},
|
||||
new(localizer["Menu3"].Value)
|
||||
};
|
||||
}
|
||||
|
||||
public static async Task<IEnumerable<MenuItem>> GetTopIconItemsAsync(IStringLocalizer localizer)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
return new List<MenuItem>
|
||||
{
|
||||
new(localizer["Menu1"].Value, icon:"fa fa-life-bouy"),
|
||||
new(localizer["Menu2"].Value, icon:"fa fa-fa")
|
||||
{
|
||||
IsActive = true,
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu1"].Value, icon:"fa fa-fa"),
|
||||
new(localizer["SubMenu2"].Value, icon:"fa fa-fa"),
|
||||
new(localizer["SubMenu3"].Value, icon:"fa fa-fa"),
|
||||
}
|
||||
},
|
||||
new(localizer["Menu3"].Value, icon:"fa fa-rebel fa-fw")
|
||||
};
|
||||
}
|
||||
|
||||
public static async Task<IEnumerable<MenuItem>> GetSideMenuItemsAsync(IStringLocalizer localizer)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
|
||||
return new List<MenuItem>
|
||||
{
|
||||
new(localizer["Menu1"].Value, icon: "fa fa-fa"),
|
||||
new(localizer["Menu2"].Value)
|
||||
{
|
||||
IsActive = true,
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu1"].Value)
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu11"].Value),
|
||||
new(localizer["SubMenu12"].Value)
|
||||
}
|
||||
},
|
||||
new(localizer["SubMenu2"].Value)
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu21"].Value),
|
||||
new(localizer["SubMenu22"].Value)
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu31"].Value),
|
||||
new(localizer["SubMenu32"].Value)
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu41"].Value),
|
||||
new(localizer["SubMenu42"].Value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new(localizer["SubMenu3"].Value)
|
||||
}
|
||||
},
|
||||
new(localizer["Menu3"].Value)
|
||||
};
|
||||
}
|
||||
|
||||
public static async Task<IEnumerable<MenuItem>> GetDisabledMenuItemsAsync(IStringLocalizer localizer)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
return new List<MenuItem>
|
||||
{
|
||||
new(localizer["Menu1"].Value)
|
||||
{
|
||||
IsActive = true,
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu1"].Value)
|
||||
}
|
||||
},
|
||||
new(localizer["Menu2"].Value)
|
||||
{
|
||||
IsDisabled = true,
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu2"].Value)
|
||||
}
|
||||
},
|
||||
new(localizer["Menu3"].Value)
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["SubMenu3"].Value)
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static BootstrapDynamicComponent BuildDynamicComponent() => BootstrapDynamicComponent.CreateComponent<Badge>(new[]
|
||||
{
|
||||
new KeyValuePair<string, object?>(nameof(Badge.Color), Color.Danger),
|
||||
new KeyValuePair<string, object?>(nameof(Badge.IsPill), true),
|
||||
new KeyValuePair<string, object?>(nameof(Badge.ChildContent), new RenderFragment(builder =>
|
||||
{
|
||||
var index = 0;
|
||||
builder.AddContent(index++, "10");
|
||||
}))
|
||||
});
|
||||
}
|
||||
|
||||
private IEnumerable<MenuItem> WidgetIconSideMenuItems { get; set; } = Enumerable.Empty<MenuItem>();
|
||||
|
||||
private IEnumerable<MenuItem> GetWidgetIconSideMenuItems()
|
||||
{
|
||||
var ret = new List<MenuItem>
|
||||
public static async Task<IEnumerable<MenuItem>> GetIconSideMenuItemsAsync(IStringLocalizer localizer)
|
||||
{
|
||||
new MenuItem() { Text = "系统设置", Icon = "fa fa-fw fa-gears" },
|
||||
new MenuItem() { Text = "权限设置", Icon = "fa fa-fw fa-users" },
|
||||
new MenuItem() {
|
||||
Text = "日志设置",
|
||||
IsActive = true,
|
||||
Icon = "fa fa-fw fa-database",
|
||||
Component = BuildDynamicComponent()
|
||||
}
|
||||
};
|
||||
|
||||
ret[0].AddItem(new MenuItem() { Text = "网站设置", Icon = "fa fa-fw fa-fa" });
|
||||
ret[0].AddItem(new MenuItem() { Text = "任务设置", Icon = "fa fa-fw fa-tasks" });
|
||||
|
||||
ret[1].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });
|
||||
|
||||
ret[2].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
|
||||
ret[2].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
|
||||
ret[2].AddItem(new MenuItem()
|
||||
{
|
||||
Text = "操作日志",
|
||||
Icon = "fa fa-fw fa-edit",
|
||||
Component = BuildDynamicComponent()
|
||||
});
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private IEnumerable<MenuItem> CollapsedIconSideMenuItems { get; set; } = Enumerable.Empty<MenuItem>();
|
||||
|
||||
private IEnumerable<MenuItem> GetCollapsedIconSideMenuItems()
|
||||
{
|
||||
var ret = new List<MenuItem>
|
||||
{
|
||||
new MenuItem() { Text = "系统设置", Icon = "fa fa-fw fa-gears" },
|
||||
new MenuItem() { Text = "权限设置", IsActive = true, Icon = "fa fa-fw fa-users" , IsCollapsed = false },
|
||||
new MenuItem() { Text = "日志设置", Icon = "fa fa-fw fa-database" }
|
||||
};
|
||||
|
||||
ret[0].AddItem(new MenuItem() { Text = "网站设置", Icon = "fa fa-fw fa-fa" });
|
||||
ret[0].AddItem(new MenuItem() { Text = "任务设置", Icon = "fa fa-fw fa-tasks" });
|
||||
|
||||
ret[1].AddItem(new MenuItem() { Text = "用户设置", Icon = "fa fa-fw fa-user" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "菜单设置", Icon = "fa fa-fw fa-dashboard" });
|
||||
ret[1].AddItem(new MenuItem() { Text = "角色设置", Icon = "fa fa-fw fa-sitemap" });
|
||||
|
||||
ret[2].AddItem(new MenuItem() { Text = "访问日志", Icon = "fa fa-fw fa-bars" });
|
||||
ret[2].AddItem(new MenuItem() { Text = "登录日志", Icon = "fa fa-fw fa-user-circle-o" });
|
||||
ret[2].AddItem(new MenuItem() { Text = "操作日志", Icon = "fa fa-fw fa-edit" });
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
private IEnumerable<MenuItem> DisabledMenuItems { get; set; } = Enumerable.Empty<MenuItem>();
|
||||
|
||||
private IEnumerable<MenuItem> GetDisabledMenuItems()
|
||||
{
|
||||
var ret = new List<MenuItem>
|
||||
{
|
||||
new MenuItem() { Text = "导航一", IsActive = true },
|
||||
new MenuItem() { Text = "导航二", IsDisabled = true },
|
||||
new MenuItem() { Text = "导航三" },
|
||||
new MenuItem() { Text = "导航四", IsDisabled = true },
|
||||
};
|
||||
|
||||
ret[1].AddItem(new MenuItem() { Text = "子菜单一", Icon = "fa fa-fa fa-fw" });
|
||||
|
||||
ret[2].AddItem(new MenuItem() { Text = "子菜单二", Icon = "fa fa-fa fa-fw" });
|
||||
ret[2].AddItem(new MenuItem() { Text = "子菜单三", Icon = "fa fa-fa fa-fw", IsDisabled = true });
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// OnInitialized 方法
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
Items = GetItems();
|
||||
IconItems = GetIconItems();
|
||||
SideMenuItems = GetSideMenuItems();
|
||||
IconSideMenuItems = GetIconSideMenuItems();
|
||||
WidgetIconSideMenuItems = GetWidgetIconSideMenuItems();
|
||||
CollapsedIconSideMenuItems = GetCollapsedIconSideMenuItems();
|
||||
DisabledMenuItems = GetDisabledMenuItems();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<AttributeItem> GetAttributes()
|
||||
{
|
||||
return new AttributeItem[]
|
||||
{
|
||||
new AttributeItem()
|
||||
await Task.Delay(1);
|
||||
return new List<MenuItem>
|
||||
{
|
||||
Name = "Items",
|
||||
Description = "菜单组件数据集合",
|
||||
Type = "IEnumerable<MenuItem>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem()
|
||||
new(localizer["System"].Value, icon: "fa fa-gears")
|
||||
{
|
||||
IsActive = true,
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["Website"].Value, icon: "fa fa-fa"),
|
||||
new(localizer["Task"].Value, icon: "fa fa-tasks")
|
||||
}
|
||||
},
|
||||
new(localizer["Authorize"].Value, icon: "fa fa-users")
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["User"].Value, icon: "fa fa-user"),
|
||||
new(localizer["Menu"].Value, icon: "fa fa-dashboard"),
|
||||
new(localizer["Role"].Value, icon: "fa fa-sitemap")
|
||||
}
|
||||
},
|
||||
new(localizer["Log"].Value, icon: "fa fa-database")
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["Access"].Value, icon: "fa fa-bars"),
|
||||
new(localizer["Login"].Value, icon: "fa fa-user-circle-o"),
|
||||
new(localizer["Operation"].Value, icon: "fa fa-edit")
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static async Task<IEnumerable<MenuItem>> GetWidgetIconSideMenuItemsAsync(IStringLocalizer localizer)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
return new List<MenuItem>
|
||||
{
|
||||
Name = "IsVertical",
|
||||
Description = "是否为侧栏",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "IsAccordion",
|
||||
Description = "是否手风琴效果",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "DisableNavigation",
|
||||
Description = "是否禁止地址栏导航",
|
||||
Type = "bool",
|
||||
ValueList = "true|false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "OnClick",
|
||||
Description = "菜单项被点击时回调此方法",
|
||||
Type = "Func<MenuItem, Task>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
}
|
||||
};
|
||||
new(localizer["System"].Value, icon: "fa fa-gears")
|
||||
{
|
||||
IsActive = true,
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["Website"].Value, icon: "fa fa-fa"),
|
||||
new(localizer["Task"].Value, icon: "fa fa-tasks")
|
||||
}
|
||||
},
|
||||
new(localizer["Authorize"].Value, icon: "fa fa-users")
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["User"].Value, icon: "fa fa-user"),
|
||||
new(localizer["Menu"].Value, icon: "fa fa-dashboard"),
|
||||
new(localizer["Role"].Value, icon: "fa fa-sitemap")
|
||||
}
|
||||
},
|
||||
new(localizer["Log"].Value, icon: "fa fa-database")
|
||||
{
|
||||
Component = BuildDynamicComponent(),
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["Access"].Value, icon: "fa fa-bars"),
|
||||
new(localizer["Login"].Value, icon: "fa fa-user-circle-o"),
|
||||
new(localizer["Operation"].Value, icon: "fa fa-edit")
|
||||
{
|
||||
Component = BuildDynamicComponent()
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public static async Task<IEnumerable<MenuItem>> GetCollapsedIconSideMenuItemsAsync(IStringLocalizer localizer)
|
||||
{
|
||||
await Task.Delay(1);
|
||||
return new List<MenuItem>
|
||||
{
|
||||
new(localizer["System"].Value, icon: "fa fa-gears")
|
||||
{
|
||||
IsActive = true,
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["Website"].Value, icon: "fa fa-fa"),
|
||||
new(localizer["Task"].Value, icon: "fa fa-tasks")
|
||||
}
|
||||
},
|
||||
new(localizer["Authorize"].Value, icon: "fa fa-users")
|
||||
{
|
||||
IsCollapsed = false,
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["User"].Value, icon: "fa fa-user"),
|
||||
new(localizer["Menu"].Value, icon: "fa fa-dashboard"),
|
||||
new(localizer["Role"].Value, icon: "fa fa-sitemap")
|
||||
}
|
||||
},
|
||||
new(localizer["Log"].Value, icon: "fa fa-database")
|
||||
{
|
||||
Items = new List<MenuItem>
|
||||
{
|
||||
new(localizer["Access"].Value, icon: "fa fa-bars"),
|
||||
new(localizer["Login"].Value, icon: "fa fa-user-circle-o"),
|
||||
new(localizer["Operation"].Value, icon: "fa fa-edit")
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,43 +8,45 @@
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect TValue="string" Items="@Items"></MultiSelect>
|
||||
<MultiSelect TValue="string" Items="@Items" @bind-Value="@Model.Address"></MultiSelect>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect TValue="string" Color="Color.Primary" Items="@Items"></MultiSelect>
|
||||
<MultiSelect TValue="string" Color="Color.Primary" Items="@Items" @bind-Value="@Model.Address"></MultiSelect>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect TValue="string" Color="Color.Success" Items="@Items"></MultiSelect>
|
||||
<MultiSelect TValue="string" Color="Color.Success" Items="@Items" @bind-Value="@Model.Address"></MultiSelect>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect TValue="string" Color="Color.Danger" Items="@Items"></MultiSelect>
|
||||
<MultiSelect TValue="string" Color="Color.Danger" Items="@Items" @bind-Value="@Model.Address"></MultiSelect>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect TValue="string" Color="Color.Warning" Items="@Items"></MultiSelect>
|
||||
<MultiSelect TValue="string" Color="Color.Warning" Items="@Items" @bind-Value="@Model.Address"></MultiSelect>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect TValue="string" Color="Color.Info" Items="@Items"></MultiSelect>
|
||||
<MultiSelect TValue="string" Color="Color.Info" Items="@Items" @bind-Value="@Model.Address"></MultiSelect>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect TValue="string" Color="Color.Secondary" Items="@Items"></MultiSelect>
|
||||
<MultiSelect TValue="string" Color="Color.Secondary" Items="@Items" @bind-Value="@Model.Address"></MultiSelect>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect TValue="string" Color="Color.Dark" Items="@Items"></MultiSelect>
|
||||
<MultiSelect TValue="string" Color="Color.Dark" Items="@Items" @bind-Value="@Model.Address"></MultiSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="双向绑定值字符串" Introduction="绑定一个逗号字符串分割的字符串">
|
||||
<p>本例中通过双向绑定 <code>SelectedItemsValue</code> 变量,通过下拉框选择更改其值</p>
|
||||
<p>
|
||||
<div><code>MutltiSelect</code> 组件数据源 <code>Items</code> 与 <b>选中值</b> <code>SelectedItemsValue</code> 均支持双向绑定;本例中通过双向绑定 <code>SelectedItemsValue</code> 变量,通过下拉框选择更改其值</div>
|
||||
</p>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect Items="@Items" @bind-Value="@SelectedItemsValue"></MultiSelect>
|
||||
<MultiSelect Items="@Items4" @bind-Value="@SelectedItemsValue"></MultiSelect>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Button Icon="fa fa-plus" Text="添加" OnClick="@AddItems" class="mr-1"></Button>
|
||||
<Button Icon="fa fa-minus" Text="减少" OnClick="@RemoveItems"></Button>
|
||||
<Button Icon="fa fa-plus" Text="添加选项" OnClick="@AddItems" class="mr-1"></Button>
|
||||
<Button Icon="fa fa-minus" Text="减少选项" OnClick="@RemoveItems"></Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -56,7 +58,7 @@
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect Items="@Items" @bind-Value="@SelectedArrayValues"></MultiSelect>
|
||||
<MultiSelect Items="@Items5" @bind-Value="@SelectedArrayValues"></MultiSelect>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Button Icon="fa fa-plus" Text="添加" OnClick="@AddListItems" class="mr-1"></Button>
|
||||
@@ -84,11 +86,11 @@
|
||||
</Block>
|
||||
|
||||
<Block Title="双向绑定枚举集合" Introduction="绑定一个泛型 <code>IEnumerable<Enum></code> 集合">
|
||||
<p>本例中通过双向绑定 <code>SelectedEnumValues</code> 集合变量,通过下拉框选择更改其值</p>
|
||||
<p>本例中通过双向绑定 <code>SelectedEnumValues</code> 集合变量,通过下拉框选择更改其值,<b>枚举</b> 类型时无需设置 <code>Items</code> 参数,额外功能是组件内部会尝试查找资源文件或者 <code>DisplayAttribute</code> 与 <code>DescriptionAttribute</code> 标签尝试进行本地化翻译工作,如本例切换到 <b>中文</b> 时枚举值为 <b>小学</b> 与 <b>中学</b></p>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect @bind-Value="@SelectedEnumValues"></MultiSelect>
|
||||
<MultiSelect @bind-Value="@SelectedEnumValues"></MultiSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -100,11 +102,11 @@
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect Items="@Items" @bind-Value="@SelectedItemsValue" ShowSearch="true" OnSearchTextChanged="@OnSearch"></MultiSelect>
|
||||
<MultiSelect Items="@Items6" @bind-Value="@SelectedItemsValue6" ShowSearch="true" OnSearchTextChanged="@OnSearch"></MultiSelect>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>@SelectedItemsValue</div>
|
||||
<div>@SelectedItemsValue6</div>
|
||||
<Logger @ref="Trace" class="mt-3" />
|
||||
</Block>
|
||||
|
||||
@@ -113,23 +115,21 @@
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect Items="@Items" @bind-Value="@SelectedItemsValue" IsDisabled="true" />
|
||||
<MultiSelect Items="@Items7" Value="@SelectedItemsValue7" IsDisabled="true" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div>@SelectedItemsValue</div>
|
||||
<Logger @ref="Trace" class="mt-3" />
|
||||
</Block>
|
||||
|
||||
<Block Title="选项改变时事件" Introduction="通过设置 <code>IsDisabled</code> 值设置组件禁用状态">
|
||||
<Block Title="选项改变时事件" Introduction="通过设置 <code>OnSelectedItemsChanged</code> 回调方法获取当前选中数据集合改变事件">
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect Items="@Items" @bind-Value="@SelectedItemsValue" OnSelectedItemsChanged="@OnSelectedItemsChanged" />
|
||||
<MultiSelect Items="@Items8" OnSelectedItemsChanged="@OnSelectedItemsChanged8" Value="@SelectedItemsValue8" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Logger @ref="Trace" />
|
||||
<Logger @ref="Trace2" />
|
||||
</Block>
|
||||
|
||||
<Block Title="客户端验证" Introduction="下拉框未选择时,点击提交按钮时拦截。">
|
||||
@@ -152,7 +152,7 @@
|
||||
<ValidateForm class="form-inline" Model="@Foo">
|
||||
<div class="row">
|
||||
<div class="form-group col-12">
|
||||
<MultiSelect Color="Color.Primary" Items="@Items" @bind-Value="@Foo.Name" />
|
||||
<MultiSelect Color="Color.Primary" Items="@Items9" @bind-Value="@Foo.Name" />
|
||||
</div>
|
||||
</div>
|
||||
</ValidateForm>
|
||||
@@ -160,7 +160,7 @@
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12">
|
||||
<MultiSelect Color="Color.Primary" Items="@Items" @bind-Value="@Foo.Name" />
|
||||
<MultiSelect Color="Color.Primary" Items="@Items10" @bind-Value="@Foo.Name" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -168,7 +168,7 @@
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12">
|
||||
<MultiSelect Color="Color.Primary" Items="@Items" @bind-Value="@Foo.Name" DisplayText="自定义姓名" ShowLabel="true" />
|
||||
<MultiSelect Color="Color.Primary" Items="@Items11" @bind-Value="@Foo.Name" DisplayText="自定义姓名" ShowLabel="true" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -176,30 +176,30 @@
|
||||
|
||||
<Block Title="选项超长文字" Introduction="候选项文字特别长">
|
||||
<div style="max-width: 400px">
|
||||
<MultiSelect Items="@LongItems" @bind-Value="@SelectedLongItemsValue" DisplayText="超长文字" ShowLabel="true"></MultiSelect>
|
||||
<MultiSelect Items="@LongItems1" @bind-Value="@SelectedLongItemsValue1" DisplayText="超长文字" ShowLabel="true"></MultiSelect>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="全选与反选按钮" Introduction="通过设置 <code>ShowSelectAllButton</code> 值设置组件显示全选与反选按钮">
|
||||
<div style="max-width: 400px">
|
||||
<MultiSelect Items="@LongItems" @bind-Value="@SelectedLongItemsValue" ShowToolbar="true" ShowSearch="true"></MultiSelect>
|
||||
<MultiSelect Items="@LongItems2" @bind-Value="@SelectedLongItemsValue2" ShowToolbar="true" ShowSearch="true"></MultiSelect>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="设置选项最大数与最小数" Introduction="通过设置 <code>Max</code> <code>Min</code> 值设置组件可选项数量限制">
|
||||
<div style="max-width: 300px">
|
||||
<p>最多可选择两个选项</p>
|
||||
<MultiSelect Items="@LongItems" @bind-Value="@SelectedMaxItemsValue" Max="2"></MultiSelect>
|
||||
<MultiSelect Items="@LongItems3" @bind-Value="@SelectedMaxItemsValue" Max="2"></MultiSelect>
|
||||
</div>
|
||||
<div style="max-width: 300px" class="mt-3">
|
||||
<p>最少选择两个选项</p>
|
||||
<MultiSelect Items="@LongItems" @bind-Value="@SelectedMinItemsValue" Min="2"></MultiSelect>
|
||||
<MultiSelect Items="@LongItems4" @bind-Value="@SelectedMinItemsValue" Min="2"></MultiSelect>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="扩展工具栏按钮" Introduction="通过设置 <code>ButtonTemplate</code> 自定义工具栏按钮实现自定义功能">
|
||||
<div style="max-width: 300px">
|
||||
<MultiSelect Items="@LongItems" @bind-Value="@SelectedLongItemsValue" ShowToolbar="true" ShowDefaultButtons="false">
|
||||
<MultiSelect Items="@LongItems5" @bind-Value="@SelectedLongItemsValue3" ShowToolbar="true" ShowDefaultButtons="false">
|
||||
<ButtonTemplate>
|
||||
<button class="btn" @onclick="@OnClickButton">测试</button>
|
||||
</ButtonTemplate>
|
||||
@@ -207,6 +207,20 @@
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="级联绑定" Introduction="通过选择第一个下拉框不同选项,第二个下拉框动态填充内容。">
|
||||
<p>本例中点击第一个下拉框,可以通过异步方法获取第二个多选框的数据源,进行赋值后,调用 <code>StateHasChanged</code> 进行对 <b>多选框</b> 重新渲染</p>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select TValue="string" Items="@Items3" OnSelectedItemChanged="@OnCascadeBindSelectClick" />
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<MultiSelect TValue="string" Items="@Items2" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" />
|
||||
|
||||
<EventTable Items="@GetEvents()" />
|
||||
|
||||
@@ -7,9 +7,9 @@ using BootstrapBlazor.Shared.Common;
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Foo = BootstrapBlazor.Shared.Pages.Components.Foo;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
@@ -18,67 +18,61 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// </summary>
|
||||
public partial class MultiSelects
|
||||
{
|
||||
/// <summary>
|
||||
/// 获得/设置 Logger 实例
|
||||
/// </summary>
|
||||
[NotNull]
|
||||
private Logger? Trace { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得 默认数据集合
|
||||
/// </summary>
|
||||
private readonly IEnumerable<SelectedItem> Items = new SelectedItem[]
|
||||
{
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Guangzhou", "广州"),
|
||||
new SelectedItem ("Shenzhen", "深圳"),
|
||||
new SelectedItem ("Chengdu", "成都"),
|
||||
new SelectedItem ("Wuhan", "武汉"),
|
||||
new SelectedItem ("Dalian", "大连"),
|
||||
new SelectedItem ("Hangzhou", "杭州"),
|
||||
new SelectedItem ("Lianyungang", "连云港"),
|
||||
};
|
||||
[NotNull]
|
||||
private Logger? Trace2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得 默认数据集合
|
||||
/// 级联绑定菜单
|
||||
/// </summary>
|
||||
private readonly IEnumerable<SelectedItem> LongItems = new SelectedItem[]
|
||||
/// <param name="item"></param>
|
||||
private async Task OnCascadeBindSelectClick(SelectedItem item)
|
||||
{
|
||||
new SelectedItem ("1", "特别甜的东瓜(特别甜的东瓜)"),
|
||||
new SelectedItem ("2", "特别甜的西瓜(特别甜的西瓜)"),
|
||||
new SelectedItem ("3", "特别甜的南瓜(特别甜的南瓜)"),
|
||||
new SelectedItem ("4", "特别甜的傻瓜(特别甜的傻瓜)"),
|
||||
new SelectedItem ("5", "特别甜的金瓜(特别甜的金瓜)"),
|
||||
new SelectedItem ("6", "特别甜的木瓜(特别甜的木瓜)"),
|
||||
new SelectedItem ("7", "特别甜的水瓜(特别甜的水瓜)"),
|
||||
new SelectedItem ("8", "特别甜的火瓜(特别甜的火瓜)"),
|
||||
new SelectedItem ("9", "特别甜的土瓜(特别甜的土瓜)"),
|
||||
};
|
||||
|
||||
private string SelectedLongItemsValue { get; set; } = "";
|
||||
private string SelectedMaxItemsValue { get; set; } = "";
|
||||
private string SelectedMinItemsValue { get; set; } = "";
|
||||
|
||||
private string SelectedItemsValue { get; set; } = "Beijing,Chengdu";
|
||||
// 模拟异步获取数据源
|
||||
await Task.Delay(100);
|
||||
if (item.Value == "Beijing")
|
||||
{
|
||||
Items2 = new List<SelectedItem>(new[]
|
||||
{
|
||||
new SelectedItem("1","朝阳区") { Active = true },
|
||||
new SelectedItem("2","海淀区")
|
||||
});
|
||||
}
|
||||
else if (item.Value == "Shanghai")
|
||||
{
|
||||
Items2 = new List<SelectedItem>(new[]
|
||||
{
|
||||
new SelectedItem("1","静安区"),
|
||||
new SelectedItem("2","黄浦区") {Active = true },
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
Items2 = new List<SelectedItem>();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private void AddItems()
|
||||
{
|
||||
SelectedItemsValue = "Beijing,Chengdu,Hangzhou,Lianyungang";
|
||||
SelectedItemsValue = "Beijing,Shanghai,Guangzhou";
|
||||
}
|
||||
|
||||
private void RemoveItems()
|
||||
{
|
||||
SelectedItemsValue = "Beijing,Chengdu";
|
||||
SelectedItemsValue = "Beijing";
|
||||
}
|
||||
|
||||
private void AddListItems()
|
||||
{
|
||||
SelectedArrayValues = "Beijing,Chengdu,Hangzhou,Lianyungang".Split(',');
|
||||
SelectedArrayValues = "Beijing,Shanghai".Split(',');
|
||||
}
|
||||
|
||||
private void RemoveListItems()
|
||||
{
|
||||
SelectedArrayValues = "Beijing,Chengdu".Split(',');
|
||||
SelectedArrayValues = new[] { "Beijing" };
|
||||
}
|
||||
|
||||
private void AddArrayItems()
|
||||
@@ -97,12 +91,19 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
|
||||
private IEnumerable<SelectedItem> OnSearch(string searchText)
|
||||
{
|
||||
Trace.Log($"搜索文字:{searchText}");
|
||||
return Items.Where(i => i.Text.Contains(searchText, System.StringComparison.OrdinalIgnoreCase));
|
||||
}
|
||||
|
||||
private Task OnSelectedItemsChanged(IEnumerable<SelectedItem> items)
|
||||
{
|
||||
Trace?.Log($"选中项集合:{string.Join(",", items.Select(i => i.Value))}");
|
||||
Trace.Log($"选中项集合:{string.Join(",", items.Select(i => i.Value))}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Task OnSelectedItemsChanged8(IEnumerable<SelectedItem> items)
|
||||
{
|
||||
Trace2.Log($"选中项集合:{string.Join(",", items.Select(i => i.Value))}");
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
@@ -115,11 +116,173 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
|
||||
}
|
||||
|
||||
private string SelectedLongItemsValue1 { get; set; } = "";
|
||||
private string SelectedLongItemsValue2 { get; set; } = "";
|
||||
private string SelectedLongItemsValue3 { get; set; } = "";
|
||||
private string SelectedMaxItemsValue { get; set; } = "";
|
||||
private string SelectedMinItemsValue { get; set; } = "";
|
||||
|
||||
private string SelectedItemsValue { get; set; } = "Beijing";
|
||||
|
||||
private string SelectedItemsValue6 { get; set; } = "Beijing";
|
||||
|
||||
private string SelectedItemsValue7 { get; set; } = "Beijing";
|
||||
|
||||
private string SelectedItemsValue8 { get; set; } = "Beijing";
|
||||
|
||||
private IEnumerable<SelectedItem> Items { get; set; } = new[] {
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Guangzhou", "广州"),
|
||||
new SelectedItem ("Shenzhen", "深圳"),
|
||||
new SelectedItem ("Chengdu", "成都"),
|
||||
new SelectedItem ("Wuhan", "武汉"),
|
||||
new SelectedItem ("Dalian", "大连"),
|
||||
new SelectedItem ("Hangzhou", "杭州"),
|
||||
new SelectedItem ("Lianyungang", "连云港")
|
||||
};
|
||||
|
||||
private List<SelectedItem> Items2 { get; set; } = new List<SelectedItem>();
|
||||
|
||||
private readonly List<SelectedItem> Items3 = new SelectedItem[]
|
||||
{
|
||||
new SelectedItem ("", "请选择 ..."),
|
||||
new SelectedItem ("Beijing", "北京") { Active = true },
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Hangzhou", "杭州")
|
||||
}.ToList();
|
||||
|
||||
private IEnumerable<SelectedItem> Items4 { get; set; } = new[] {
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Guangzhou", "广州")
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> Items5 { get; set; } = new[] {
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Guangzhou", "广州")
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> Items6 { get; set; } = new[] {
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Guangzhou", "广州")
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> Items7 { get; set; } = new[] {
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Guangzhou", "广州")
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> Items8 { get; set; } = new[] {
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Guangzhou", "广州")
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> Items9 { get; set; } = new[] {
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Guangzhou", "广州")
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> Items10 { get; set; } = new[] {
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Guangzhou", "广州")
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> Items11 { get; set; } = new[] {
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海"),
|
||||
new SelectedItem ("Guangzhou", "广州")
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> LongItems { get; set; } = new[]
|
||||
{
|
||||
new SelectedItem ("1", "特别甜的东瓜(特别甜的东瓜)"),
|
||||
new SelectedItem ("2", "特别甜的西瓜(特别甜的西瓜)"),
|
||||
new SelectedItem ("3", "特别甜的南瓜(特别甜的南瓜)"),
|
||||
new SelectedItem ("4", "特别甜的傻瓜(特别甜的傻瓜)"),
|
||||
new SelectedItem ("5", "特别甜的金瓜(特别甜的金瓜)"),
|
||||
new SelectedItem ("6", "特别甜的木瓜(特别甜的木瓜)"),
|
||||
new SelectedItem ("7", "特别甜的水瓜(特别甜的水瓜)"),
|
||||
new SelectedItem ("8", "特别甜的火瓜(特别甜的火瓜)"),
|
||||
new SelectedItem ("9", "特别甜的土瓜(特别甜的土瓜)"),
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> LongItems1 { get; set; } = new[]
|
||||
{
|
||||
new SelectedItem ("1", "特别甜的东瓜(特别甜的东瓜)"),
|
||||
new SelectedItem ("2", "特别甜的西瓜(特别甜的西瓜)"),
|
||||
new SelectedItem ("3", "特别甜的南瓜(特别甜的南瓜)"),
|
||||
new SelectedItem ("4", "特别甜的傻瓜(特别甜的傻瓜)"),
|
||||
new SelectedItem ("5", "特别甜的金瓜(特别甜的金瓜)"),
|
||||
new SelectedItem ("6", "特别甜的木瓜(特别甜的木瓜)"),
|
||||
new SelectedItem ("7", "特别甜的水瓜(特别甜的水瓜)"),
|
||||
new SelectedItem ("8", "特别甜的火瓜(特别甜的火瓜)"),
|
||||
new SelectedItem ("9", "特别甜的土瓜(特别甜的土瓜)"),
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> LongItems2 { get; set; } = new[]
|
||||
{
|
||||
new SelectedItem ("1", "特别甜的东瓜(特别甜的东瓜)"),
|
||||
new SelectedItem ("2", "特别甜的西瓜(特别甜的西瓜)"),
|
||||
new SelectedItem ("3", "特别甜的南瓜(特别甜的南瓜)"),
|
||||
new SelectedItem ("4", "特别甜的傻瓜(特别甜的傻瓜)"),
|
||||
new SelectedItem ("5", "特别甜的金瓜(特别甜的金瓜)"),
|
||||
new SelectedItem ("6", "特别甜的木瓜(特别甜的木瓜)"),
|
||||
new SelectedItem ("7", "特别甜的水瓜(特别甜的水瓜)"),
|
||||
new SelectedItem ("8", "特别甜的火瓜(特别甜的火瓜)"),
|
||||
new SelectedItem ("9", "特别甜的土瓜(特别甜的土瓜)"),
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> LongItems3 { get; set; } = new[]
|
||||
{
|
||||
new SelectedItem ("1", "特别甜的东瓜(特别甜的东瓜)"),
|
||||
new SelectedItem ("2", "特别甜的西瓜(特别甜的西瓜)"),
|
||||
new SelectedItem ("3", "特别甜的南瓜(特别甜的南瓜)"),
|
||||
new SelectedItem ("4", "特别甜的傻瓜(特别甜的傻瓜)"),
|
||||
new SelectedItem ("5", "特别甜的金瓜(特别甜的金瓜)"),
|
||||
new SelectedItem ("6", "特别甜的木瓜(特别甜的木瓜)"),
|
||||
new SelectedItem ("7", "特别甜的水瓜(特别甜的水瓜)"),
|
||||
new SelectedItem ("8", "特别甜的火瓜(特别甜的火瓜)"),
|
||||
new SelectedItem ("9", "特别甜的土瓜(特别甜的土瓜)"),
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> LongItems4 { get; set; } = new[]
|
||||
{
|
||||
new SelectedItem ("1", "特别甜的东瓜(特别甜的东瓜)"),
|
||||
new SelectedItem ("2", "特别甜的西瓜(特别甜的西瓜)"),
|
||||
new SelectedItem ("3", "特别甜的南瓜(特别甜的南瓜)"),
|
||||
new SelectedItem ("4", "特别甜的傻瓜(特别甜的傻瓜)"),
|
||||
new SelectedItem ("5", "特别甜的金瓜(特别甜的金瓜)"),
|
||||
new SelectedItem ("6", "特别甜的木瓜(特别甜的木瓜)"),
|
||||
new SelectedItem ("7", "特别甜的水瓜(特别甜的水瓜)"),
|
||||
new SelectedItem ("8", "特别甜的火瓜(特别甜的火瓜)"),
|
||||
new SelectedItem ("9", "特别甜的土瓜(特别甜的土瓜)"),
|
||||
};
|
||||
|
||||
private IEnumerable<SelectedItem> LongItems5 { get; set; } = new[]
|
||||
{
|
||||
new SelectedItem ("1", "特别甜的东瓜(特别甜的东瓜)"),
|
||||
new SelectedItem ("2", "特别甜的西瓜(特别甜的西瓜)"),
|
||||
new SelectedItem ("3", "特别甜的南瓜(特别甜的南瓜)"),
|
||||
new SelectedItem ("4", "特别甜的傻瓜(特别甜的傻瓜)"),
|
||||
new SelectedItem ("5", "特别甜的金瓜(特别甜的金瓜)"),
|
||||
new SelectedItem ("6", "特别甜的木瓜(特别甜的木瓜)"),
|
||||
new SelectedItem ("7", "特别甜的水瓜(特别甜的水瓜)"),
|
||||
new SelectedItem ("8", "特别甜的火瓜(特别甜的火瓜)"),
|
||||
new SelectedItem ("9", "特别甜的土瓜(特别甜的土瓜)"),
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 获得事件方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<EventItem> GetEvents() => new EventItem[]
|
||||
private static IEnumerable<EventItem> GetEvents() => new[]
|
||||
{
|
||||
new EventItem()
|
||||
{
|
||||
@@ -139,7 +302,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// 获得属性方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new[]
|
||||
{
|
||||
// TODO: 移动到数据库中
|
||||
new AttributeItem() {
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
var ret = new List<NavLink>();
|
||||
var link = new NavLink();
|
||||
link.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object>()
|
||||
link.SetParametersAsync(ParameterView.FromDictionary(new Dictionary<string, object?>()
|
||||
{
|
||||
["href"] = WebsiteOption.Value.AdminUrl,
|
||||
["class"] = "nav-link nav-item",
|
||||
@@ -38,7 +38,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// 获得属性方法
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
{
|
||||
// TODO: 移动到数据库中
|
||||
new AttributeItem() {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<PopConfirmButton Placement="Placement.Bottom" ConfirmButtonColor="Color.Danger" Text="下面弹框" Content="这是一段内容确定删除吗?" OnConfirm="@OnConfirm" OnClose="@OnClose" />
|
||||
</div>
|
||||
<div class="d-flex justify-content-between m-4 align-items-center flex-fill">
|
||||
<PopConfirmButton Placement="Placement.Right" CloseButtonText="取消" Text="右侧弹窗" Content="这是一段内容确定删除吗?" OnConfirm="@OnConfirm" OnClose="@OnClose" />
|
||||
<PopConfirmButton Placement="Placement.Right" Text="右侧弹窗" Content="这是一段内容确定删除吗?" OnConfirm="@OnConfirm" OnClose="@OnClose" />
|
||||
<PopConfirmButton Placement="Placement.Left" Text="左侧弹窗" Content="这是一段内容确定删除吗?" OnConfirm="@OnConfirm" OnClose="@OnClose" />
|
||||
</div>
|
||||
<div class="d-flex justify-content-center">
|
||||
|
||||
@@ -103,7 +103,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
DefaultValue = "fa fa-exclamation-circle text-info"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "Cotent",
|
||||
Name = "Content",
|
||||
Description = "显示文字",
|
||||
Type = "string",
|
||||
ValueList = "",
|
||||
|
||||
@@ -5,7 +5,33 @@
|
||||
<h4>可简单设置一行显示的组件数量</h4>
|
||||
|
||||
<Block Title="放置普通控件" Introduction="将自己的组件放到 <code>Row</code> 内部即可">
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.Three">
|
||||
<p><b>行显示 3 个,采用 <code>Row</code></b></p>
|
||||
<Row ItemsPerRow="ItemsPerRow.Three">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<h5 class="card-title">Card 1</h5>
|
||||
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
|
||||
<a href="#" class="btn btn-primary">Go somewhere</a>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardBody>
|
||||
<h5 class="card-title">Card 2</h5>
|
||||
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
|
||||
<a href="#" class="btn btn-primary">Go somewhere</a>
|
||||
</CardBody>
|
||||
</Card>
|
||||
<Card>
|
||||
<CardBody>
|
||||
<h5 class="card-title">Card 3</h5>
|
||||
<p class="card-text">Some quick example text to build on the card title and make up the bulk of the card's content.</p>
|
||||
<a href="#" class="btn btn-primary">Go somewhere</a>
|
||||
</CardBody>
|
||||
</Card>
|
||||
</Row>
|
||||
|
||||
<p class="mt-3"><b>行显示 3 个,采用 <code>FormRow</code></b></p>
|
||||
<Row RowType="RowType.FormRow" ItemsPerRow="ItemsPerRow.Three">
|
||||
<Card>
|
||||
<CardBody>
|
||||
<h5 class="card-title">Card 1</h5>
|
||||
@@ -29,79 +55,148 @@
|
||||
</Card>
|
||||
</Row>
|
||||
</Block>
|
||||
<Block Title="放置表单控件(内联)" Introduction="当放置表单控件时,可以指定RowType为FormInline,会将Label显示在左边,控件显示原始大小">
|
||||
|
||||
<Block Title="放置表单控件(内联)" Introduction="当放置表单控件时,可以指定 <code>RowType</code> 为 <code>Inline</code>,会将 <b>Label</b> 显示在左边,控件显示原始大小">
|
||||
<p>本例中 <code>Row</code> 组件内置于 <code>ValidateForm</code> 组件内,自动增加前置 <code>Label</code> 标签</p>
|
||||
<ValidateForm Model="@Model">
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.Three" RowType="RowTypeEnum.FormInline" >
|
||||
<CheckboxList @bind-Value="@Educations" />
|
||||
<Row ItemsPerRow="ItemsPerRow.Three" RowType="RowType.Inline">
|
||||
<CheckboxList @bind-Value="@Model.Hobby" Items="Hobbys" />
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
<BootstrapInput @bind-Value="@Model.DateTime" />
|
||||
<BootstrapInput @bind-Value="@Model.Id" />
|
||||
<BootstrapInput @bind-Value="@Model.Complete" />
|
||||
<DateTimePicker @bind-Value="@Model.DateTime" />
|
||||
<BootstrapInputNumber @bind-Value="@Model.Count" />
|
||||
<Switch @bind-Value="@Model.Complete" />
|
||||
<Select @bind-Value="@Model.Education" />
|
||||
</Row>
|
||||
</ValidateForm>
|
||||
</Block>
|
||||
<Block Title="放置表单控件(充满)" Introduction="当放置表单控件时,可以指定RowType为FormRow,会将Label显示在上边,控件充满">
|
||||
|
||||
<Block Title="放置表单控件(充满)" Introduction="当放置表单控件时,可以指定 <code>RowType</code> 为 <code>FormRow</code>,会将 <b>Label</b> 显示在上边,控件充满">
|
||||
<p>本例中 <code>Row</code> 组件内置于 <code>ValidateForm</code> 组件内,自动增加前置 <code>Label</code> 标签</p>
|
||||
<ValidateForm Model="@Model">
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.Three" RowType="RowTypeEnum.FormRow" MaxCount="5">
|
||||
<CheckboxList @bind-Value="@Educations" />
|
||||
<Row ItemsPerRow="ItemsPerRow.Three" RowType="RowType.FormRow">
|
||||
<CheckboxList @bind-Value="@Model.Hobby" Items="Hobbys" />
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
<BootstrapInput @bind-Value="@Model.DateTime" />
|
||||
<BootstrapInput @bind-Value="@Model.Id" />
|
||||
<BootstrapInput @bind-Value="@Model.Complete" />
|
||||
<DateTimePicker @bind-Value="@Model.DateTime" />
|
||||
<BootstrapInputNumber @bind-Value="@Model.Count" />
|
||||
<Switch @bind-Value="@Model.Complete" />
|
||||
<Select @bind-Value="@Model.Education" />
|
||||
</Row>
|
||||
</ValidateForm>
|
||||
</Block>
|
||||
<Block Title="Row嵌套" Introduction="Row中还可以嵌套Row,比如下面最外层的Row设置一行显示两个控件,第一个是TextBox,第二个还是个Row,第二个Row继续设置显示两个控件">
|
||||
|
||||
<Block Title="嵌套使用" Introduction="<code>Row</code> 组件支持嵌套使用,比如下面最外层的 <code>Row</code> 设置一行显示两个控件,第一个是 <code>TextBox</code>,第二个还是 <code>Row</code>,第二个 <code>Row</code> 继续设置显示两个控件">
|
||||
<p>本例中 <code>Row</code> 组件内置于 <code>ValidateForm</code> 组件内,自动增加前置 <code>Label</code> 标签</p>
|
||||
<Pre><Row ItemsPerRow="ItemsPerRow.Two" RowType="RowType.FormRow">
|
||||
<BootstrapInput @@bind-Value="@@Model.Name" />
|
||||
<Row ItemsPerRow="ItemsPerRow.Two">
|
||||
<Switch @@bind-Value="@@Model.Complete" />
|
||||
<BootstrapInput @@bind-Value="@@Model.Address" />
|
||||
</Row>
|
||||
</Row>
|
||||
</Pre>
|
||||
<ValidateForm Model="@Model">
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.Two" RowType="RowTypeEnum.FormRow">
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.Two">
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
<Row ItemsPerRow="ItemsPerRow.Two" RowType="RowType.FormRow">
|
||||
<BootstrapInput @bind-Value="@Model.Name" />
|
||||
<Row ItemsPerRow="ItemsPerRow.Two">
|
||||
<Switch @bind-Value="@Model.Complete" />
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
</Row>
|
||||
</Row>
|
||||
</ValidateForm>
|
||||
</Block>
|
||||
<Block Title="子Row跨列" Introduction="子Row中通过指定ColSpan可以设置跨父Row的列数,组合这些功能可以实现复杂布局">
|
||||
|
||||
<Block Title="跨列功能" Introduction="<code>Row</code> 组件可以通过指定 <code>ColSpan</code> 值设置跨列数,组合这些功能可以实现复杂布局">
|
||||
<p>本例中 <code>Row</code> 组件内置于 <code>ValidateForm</code> 组件内,自动增加前置 <code>Label</code> 标签</p>
|
||||
|
||||
<p><b>行显示 4 个</b></p>
|
||||
<Pre><Row ItemsPerRow="ItemsPerRow.Four" RowType="RowType.FormRow">
|
||||
<BootstrapInput @@bind-Value="@@Model.Name" />
|
||||
<BootstrapInput @@bind-Value="@@Model.Address" />
|
||||
<BootstrapInputNumber @@bind-Value="@@Model.Count" />
|
||||
<Select @@bind-Value="@@Model.Education" />
|
||||
</Row>
|
||||
</Pre>
|
||||
<ValidateForm Model="@Model">
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.Four" RowType="RowTypeEnum.FormRow">
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
<Row ItemsPerRow="ItemsPerRow.Four" RowType="RowType.FormRow">
|
||||
<BootstrapInput @bind-Value="@Model.Name" />
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
<BootstrapInputNumber @bind-Value="@Model.Count" />
|
||||
<Select @bind-Value="@Model.Education" />
|
||||
</Row>
|
||||
</ValidateForm>
|
||||
|
||||
<p><b>行显示 2 个</b></p>
|
||||
<Pre><Row ItemsPerRow="ItemsPerRow.Two" RowType="RowType.FormRow">
|
||||
<BootstrapInput @@bind-Value="@@Model.Name" />
|
||||
<BootstrapInput @@bind-Value="@@Model.Address" />
|
||||
</Row>
|
||||
</Pre>
|
||||
<ValidateForm Model="@Model">
|
||||
<Row ItemsPerRow="ItemsPerRow.Two" RowType="RowType.FormRow">
|
||||
<BootstrapInput @bind-Value="@Model.Name" />
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
</Row>
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.Two" RowType="RowTypeEnum.FormRow">
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
</Row>
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.Four" RowType="RowTypeEnum.FormRow">
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
</ValidateForm>
|
||||
|
||||
<p><b>行显示 4 个 <code>Address</code> 占 2 列</b></p>
|
||||
<Pre><Row ItemsPerRow="ItemsPerRow.Four" RowType="RowType.FormRow">
|
||||
<BootstrapInput @@bind-Value="@@Model.Name" />
|
||||
<Row ColSpan="2">
|
||||
<BootstrapInput @@bind-Value="@@Model.Address" />
|
||||
</Row>
|
||||
<Select @@bind-Value="@Model.Education" />
|
||||
</Row>
|
||||
</Pre>
|
||||
<ValidateForm Model="@Model">
|
||||
<Row ItemsPerRow="ItemsPerRow.Four" RowType="RowType.FormRow">
|
||||
<BootstrapInput @bind-Value="@Model.Name" />
|
||||
<Row ColSpan="2">
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
</Row>
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
<Select @bind-Value="@Model.Education" />
|
||||
</Row>
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.Four" RowType="RowTypeEnum.FormRow">
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
</ValidateForm>
|
||||
|
||||
<p><b>行显示 4 个,第二个组件 <code>ColSpan</code> 设置为 3</b></p>
|
||||
<Pre><Row ItemsPerRow="ItemsPerRow.Four" RowType="RowType.FormRow">
|
||||
<BootstrapInput @@bind-Value="@@Model.Name" />
|
||||
<Row ColSpan="3">
|
||||
<BootstrapInput @@bind-Value="@@Model.Address" />
|
||||
</Row>
|
||||
</Row>
|
||||
</Pre>
|
||||
<ValidateForm Model="@Model">
|
||||
<Row ItemsPerRow="ItemsPerRow.Four" RowType="RowType.FormRow">
|
||||
<BootstrapInput @bind-Value="@Model.Name" />
|
||||
<Row ColSpan="3">
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
</Row>
|
||||
</Row>
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.Four" RowType="RowTypeEnum.FormRow">
|
||||
</ValidateForm>
|
||||
|
||||
<p><b>行显示 2 个,第一个组件 <code>ColSpan</code> 设置为 3</b></p>
|
||||
<Pre><Row ItemsPerRow="ItemsPerRow.Four" RowType="RowType.FormRow">
|
||||
<Row ColSpan="3">
|
||||
<CheckboxList @@bind-Value="@@Model.Hobby" Items="@@Hobbys" />
|
||||
</Row>
|
||||
<BootstrapInput @@bind-Value="@@Model.Address" />
|
||||
</Row>
|
||||
</Pre>
|
||||
<ValidateForm Model="@Model">
|
||||
<Row ItemsPerRow="ItemsPerRow.Four" RowType="RowType.FormRow">
|
||||
<Row ColSpan="3">
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
<CheckboxList @bind-Value="@Model.Hobby" Items="@Hobbys" />
|
||||
</Row>
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
</Row>
|
||||
<Row ItemsPerRow="ItemsPerRowEnum.One">
|
||||
</ValidateForm>
|
||||
|
||||
<p>行显示一个组件</p>
|
||||
<ValidateForm Model="@Model">
|
||||
<Row ItemsPerRow="ItemsPerRow.One">
|
||||
<BootstrapInput @bind-Value="@Model.Address" />
|
||||
</Row>
|
||||
</ValidateForm>
|
||||
</Block>
|
||||
|
||||
<Tips>
|
||||
注意,由于Blazor还无法区分子组件的级层,如果Row中包含的组件还输出了其他子组件,Row也会加载子组件导致排版错误,可以通过指定MaxCount来指定Row中显示组件的个数
|
||||
</Tips>
|
||||
|
||||
|
||||
<AttributeTable Items="@GetAttributes()" />
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using BootstrapBlazor.Shared.Common;
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
@@ -14,17 +19,33 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// </summary>
|
||||
public sealed partial class Rows
|
||||
{
|
||||
private Foo Model { get; } = new Foo()
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IStringLocalizer<Foo>? Localizer { get; set; }
|
||||
|
||||
private RowFoo Model { get; } = new()
|
||||
{
|
||||
Name = "张三",
|
||||
Count = 23,
|
||||
Address = "测试地址",
|
||||
DateTime = new DateTime(1997, 12, 05),
|
||||
Education = EnumEducation.Middel
|
||||
Educations = new List<EnumEducation> { EnumEducation.Primary, EnumEducation.Middel }
|
||||
};
|
||||
|
||||
private List<EnumEducation> Educations = new List<EnumEducation> { EnumEducation.Middel, EnumEducation.Primary };
|
||||
private IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
[NotNull]
|
||||
private IEnumerable<SelectedItem>? Hobbys { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// OnInitialized 方法
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
Hobbys = Foo.GenerateHobbys(Localizer);
|
||||
}
|
||||
|
||||
private static IEnumerable<AttributeItem> GetAttributes() => new AttributeItem[]
|
||||
{
|
||||
new AttributeItem() {
|
||||
Name = "ItemsPerRow",
|
||||
@@ -54,8 +75,17 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
ValueList = "-",
|
||||
DefaultValue = "null"
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
private class RowFoo : Foo
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Required(ErrorMessage = "请选择学历")]
|
||||
[Display(Name = "学历")]
|
||||
[AutoGenerateColumn(Order = 60)]
|
||||
public List<EnumEducation>? Educations { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,31 +6,32 @@
|
||||
<h4>当选项过多时,使用下拉菜单展示并选择内容</h4>
|
||||
|
||||
<Block Title="Select 下拉选择框" Introduction="提供各种颜色的下拉选择框">
|
||||
<p>本例中,第一个下拉框没有进行 <code>Value</code> 双向绑定,所以选择不同选项时仅自己变化,其余下拉框共用同一数据源 <code>Items</code> 并且双向绑定 <code>Value</code> 值,选择不同选项时一同变化</p>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select TValue="string" Items="@Items" OnSelectedItemChanged="@OnItemChanged"></Select>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select TValue="string" Color="Color.Primary" Items="@Items" OnSelectedItemChanged="@OnItemChanged"></Select>
|
||||
<Select Color="Color.Primary" Items="@Items" OnSelectedItemChanged="@OnItemChanged" @bind-Value="@Model.Name"></Select>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select TValue="string" Color="Color.Success" Items="@Items" OnSelectedItemChanged="@OnItemChanged"></Select>
|
||||
<Select Color="Color.Success" @bind-Items="@Items" OnSelectedItemChanged="@OnItemChanged" @bind-Value="@Model.Name"></Select>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select TValue="string" Color="Color.Danger" Items="@Items" OnSelectedItemChanged="@OnItemChanged"></Select>
|
||||
<Select Color="Color.Danger" @bind-Items="@Items" OnSelectedItemChanged="@OnItemChanged" @bind-Value="@Model.Name"></Select>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select TValue="string" Color="Color.Warning" Items="@Items" OnSelectedItemChanged="@OnItemChanged"></Select>
|
||||
<Select Color="Color.Warning" @bind-Items="@Items" OnSelectedItemChanged="@OnItemChanged" @bind-Value="@Model.Name"></Select>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select TValue="string" Color="Color.Info" Items="@Items" OnSelectedItemChanged="@OnItemChanged"></Select>
|
||||
<Select Color="Color.Info" @bind-Items="@Items" OnSelectedItemChanged="@OnItemChanged" @bind-Value="@Model.Name"></Select>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select TValue="string" Color="Color.Secondary" Items="@Items" OnSelectedItemChanged="@OnItemChanged"></Select>
|
||||
<Select Color="Color.Secondary" @bind-Items="@Items" OnSelectedItemChanged="@OnItemChanged" @bind-Value="@Model.Name"></Select>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select TValue="string" Color="Color.Dark" Items="@Items" OnSelectedItemChanged="@OnItemChanged"></Select>
|
||||
<Select Color="Color.Dark" @bind-Items="@Items" OnSelectedItemChanged="@OnItemChanged" @bind-Value="@Model.Name"></Select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -63,6 +64,14 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<p>下拉框内选项 <b>禁用</b> 示例</p>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select TValue="string" Items="@Items4" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Block>
|
||||
|
||||
<Block Title="Select 双向绑定" Introduction="通过 <code>Select</code> 组件绑定 <code>Model.Name</code> 属性,改变下拉框选项时,文本框内的数值随之改变。">
|
||||
@@ -85,7 +94,7 @@
|
||||
<Select TValue="string" Items="@Items3" OnSelectedItemChanged="@OnCascadeBindSelectClick" />
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select @ref="Select2" TValue="string" Items="@Items2" />
|
||||
<Select TValue="string" Items="@Items2" />
|
||||
</div>
|
||||
<div class="form-group col-12">
|
||||
<Button Text="弹窗中级联示例" OnClickWithoutRender="@OnShowDialog" />
|
||||
@@ -179,11 +188,20 @@
|
||||
</Block>
|
||||
|
||||
<Block Title="枚举数据" Introduction="<code>Select</code> 组件绑定枚举类型示例">
|
||||
<p>本次展现的是通过 <code>Select</code> 组件绑定枚举类型 <code>EnumEducation</code>,通过选项的更改绑定数据</p>
|
||||
<p>当绑定值为可为空枚举类型时,组件内部自动通过 <code>PlaceHolder</code> 值添加首选项,未设置 <code>PlaceHolder</code> 值时,使用资源文件中的 <b>请选择 ...</b> 作为首选项,本示例绑定 <code>EnumEducation</code> 枚举类型</p>
|
||||
<p>绑定值为枚举类型时,设置 <code>PalceHolder</code> 无效</p>
|
||||
<div class="form-inline">
|
||||
<div class="row">
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select @bind-Value="@SelectedEnumItem">
|
||||
<Select @bind-Value="@SelectedEnumItem1" PlaceHolder="@Localizer["PlaceHolder"]" ShowLabel="true" DisplayText="可为空">
|
||||
</Select>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select @bind-Value="@SelectedEnumItem1" ShowLabel="true" DisplayText="可为空">
|
||||
</Select>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
<Select @bind-Value="@SelectedEnumItem" ShowLabel="true" DisplayText="不为空">
|
||||
</Select>
|
||||
</div>
|
||||
<div class="form-group col-12 col-sm-6">
|
||||
|
||||
@@ -5,8 +5,12 @@
|
||||
using BootstrapBlazor.Components;
|
||||
using BootstrapBlazor.Shared.Common;
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
@@ -31,10 +35,14 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// </summary>
|
||||
private Logger? Trace { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IStringLocalizer<Selects>? Localizer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得 默认数据集合
|
||||
/// </summary>
|
||||
private readonly IEnumerable<SelectedItem> Items = new SelectedItem[]
|
||||
private IEnumerable<SelectedItem> Items { get; set; } = new[]
|
||||
{
|
||||
new SelectedItem ("Beijing", "北京"),
|
||||
new SelectedItem ("Shanghai", "上海") { Active = true },
|
||||
@@ -43,7 +51,17 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
/// <summary>
|
||||
/// 获得 默认数据集合
|
||||
/// </summary>
|
||||
private readonly IEnumerable<SelectedItem> StringItems = new SelectedItem[]
|
||||
private readonly IEnumerable<SelectedItem> Items4 = new[]
|
||||
{
|
||||
new SelectedItem ("Beijing", "北京") { IsDisabled = true},
|
||||
new SelectedItem ("Shanghai", "上海") { Active = true },
|
||||
new SelectedItem ("Guangzhou", "广州")
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// 获得 默认数据集合
|
||||
/// </summary>
|
||||
private readonly IEnumerable<SelectedItem> StringItems = new[]
|
||||
{
|
||||
new SelectedItem ("1", "1"),
|
||||
new SelectedItem ("12", "12"),
|
||||
@@ -92,47 +110,48 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
private Task OnItemChanged(SelectedItem item)
|
||||
{
|
||||
Trace?.Log($"SelectedItem Text: {item.Text} Value: {item.Value} Selected");
|
||||
StateHasChanged();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private Select<string>? Select2 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 级联绑定菜单
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
private Task OnCascadeBindSelectClick(SelectedItem item)
|
||||
private async Task OnCascadeBindSelectClick(SelectedItem item)
|
||||
{
|
||||
_item2.Clear();
|
||||
// 模拟异步通讯切换线程
|
||||
await Task.Delay(10);
|
||||
if (item.Value == "Beijing")
|
||||
{
|
||||
_item2.AddRange(new SelectedItem[]
|
||||
Items2 = new SelectedItem[]
|
||||
{
|
||||
new SelectedItem("1","朝阳区"),
|
||||
new SelectedItem("1","朝阳区") { Active = true},
|
||||
new SelectedItem("2","海淀区"),
|
||||
});
|
||||
};
|
||||
}
|
||||
else if (item.Value == "Shanghai")
|
||||
{
|
||||
_item2.AddRange(new SelectedItem[]
|
||||
Items2 = new SelectedItem[]
|
||||
{
|
||||
new SelectedItem("1","静安区"),
|
||||
new SelectedItem("2","黄浦区"),
|
||||
});
|
||||
new SelectedItem("2","黄浦区") { Active = true } ,
|
||||
};
|
||||
}
|
||||
Select2?.SetItems(_item2);
|
||||
return Task.CompletedTask;
|
||||
else
|
||||
{
|
||||
Items2 = Enumerable.Empty<SelectedItem>();
|
||||
}
|
||||
StateHasChanged();
|
||||
}
|
||||
|
||||
private Task OnShowDialog() => Dialog.Show(new DialogOption()
|
||||
{
|
||||
Title = "弹窗中使用级联下拉框",
|
||||
Component = DynamicComponent.CreateComponent<CustomerSelectDialog>()
|
||||
Component = BootstrapDynamicComponent.CreateComponent<CustomerSelectDialog>()
|
||||
});
|
||||
|
||||
private readonly List<SelectedItem> _item2 = new();
|
||||
|
||||
private IEnumerable<SelectedItem> Items2 => _item2;
|
||||
private IEnumerable<SelectedItem>? Items2 { get; set; }
|
||||
|
||||
private IEnumerable<SelectedItem> NullableIntItems { get; set; } = new SelectedItem[]
|
||||
{
|
||||
@@ -164,6 +183,8 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
|
||||
private EnumEducation SelectedEnumItem { get; set; } = EnumEducation.Primary;
|
||||
|
||||
private EnumEducation? SelectedEnumItem1 { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获得事件方法
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/swals"
|
||||
@inject SwalService SwalService
|
||||
|
||||
<h3>SweetAlert 弹窗组件</h3>
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using BootstrapBlazor.Shared.Pages.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
@@ -35,6 +36,10 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
Content = "我是 Content"
|
||||
});
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private SwalService? SwalService { get; set; }
|
||||
|
||||
private async Task ShowButtons()
|
||||
{
|
||||
var op = new SwalOption()
|
||||
@@ -78,7 +83,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
Title = "Oops...",
|
||||
Content = "Something went wrong!",
|
||||
ShowFooter = true,
|
||||
FooterTemplate = DynamicComponent.CreateComponent<SwalFooter>().Render()
|
||||
FooterTemplate = BootstrapDynamicComponent.CreateComponent<SwalFooter>().Render()
|
||||
};
|
||||
await SwalService.Show(op);
|
||||
}
|
||||
@@ -93,7 +98,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
ShowFooter = true,
|
||||
IsAutoHide = true,
|
||||
Delay = 4000,
|
||||
FooterTemplate = DynamicComponent.CreateComponent<SwalFooter>().Render()
|
||||
FooterTemplate = BootstrapDynamicComponent.CreateComponent<SwalFooter>().Render()
|
||||
};
|
||||
await SwalService.Show(op);
|
||||
}
|
||||
@@ -117,7 +122,7 @@ namespace BootstrapBlazor.Shared.Pages
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<AttributeItem> GetAttributes()
|
||||
private static IEnumerable<AttributeItem> GetAttributes()
|
||||
{
|
||||
return new AttributeItem[]
|
||||
{
|
||||
|
||||
@@ -327,6 +327,13 @@ namespace BootstrapBlazor.Shared.Pages.Table
|
||||
ValueList = "true / false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "IsTree",
|
||||
Description = "是否为树形数据",
|
||||
Type = "boolean",
|
||||
ValueList = "true / false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "ClickToSelect",
|
||||
Description = "点击行即选中本行",
|
||||
@@ -355,6 +362,20 @@ namespace BootstrapBlazor.Shared.Pages.Table
|
||||
ValueList = "true / false",
|
||||
DefaultValue = "false"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "ShowResetSearch",
|
||||
Description = "显示清空搜索按钮",
|
||||
Type = "boolean",
|
||||
ValueList = "true / false",
|
||||
DefaultValue = "true"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "ShowAdvancedSearch",
|
||||
Description = "显示高级搜索按钮",
|
||||
Type = "boolean",
|
||||
ValueList = "true / false",
|
||||
DefaultValue = "true"
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "ShowToolbar",
|
||||
Description = "显示 Toolbar",
|
||||
@@ -453,6 +474,13 @@ namespace BootstrapBlazor.Shared.Pages.Table
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "OnEditAsync",
|
||||
Description = "编辑按钮异步回调方法",
|
||||
Type = "Func<TItem, Task>",
|
||||
ValueList = " — ",
|
||||
DefaultValue = " — "
|
||||
},
|
||||
new AttributeItem() {
|
||||
Name = "OnSaveAsync",
|
||||
Description = "保存按钮异步回调方法",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@inherits TablesBase
|
||||
@page "/tables/autorefresh"
|
||||
@page "/tables/autorefresh"
|
||||
|
||||
<h3>自动刷新表格功能</h3>
|
||||
|
||||
@@ -18,11 +17,7 @@
|
||||
<TableColumn @bind-Field="@context.Name" Width="100" />
|
||||
<TableColumn @bind-Field="@context.Address" />
|
||||
<TableColumn @bind-Field="@context.Count" />
|
||||
<TableColumn @bind-Field="@context.Complete">
|
||||
<Template Context="v">
|
||||
<Switch IsDisabled="true" Value="v.Value" ShowInnerText="true" OnInnerText="是" OffInnerText="否" />
|
||||
</Template>
|
||||
</TableColumn>
|
||||
<TableColumn @bind-Field="@context.Complete" ComponentType="typeof(Switch)" />
|
||||
</TableColumns>
|
||||
</Table>
|
||||
</Block>
|
||||
|
||||
@@ -4,8 +4,11 @@
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.Extensions.Localization;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -16,6 +19,15 @@ namespace BootstrapBlazor.Shared.Pages.Table
|
||||
/// </summary>
|
||||
public partial class TablesAutoRefresh
|
||||
{
|
||||
private static readonly Random random = new();
|
||||
|
||||
[NotNull]
|
||||
private List<Foo>? Items { get; set; }
|
||||
|
||||
[Inject]
|
||||
[NotNull]
|
||||
private IStringLocalizer<Foo>? Localizer { get; set; }
|
||||
|
||||
private List<Foo> AutoItems { get; set; } = new List<Foo>();
|
||||
|
||||
/// <summary>
|
||||
@@ -25,24 +37,19 @@ namespace BootstrapBlazor.Shared.Pages.Table
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
AutoItems = Items.Take(2).ToList();
|
||||
AutoItems = Foo.GenerateFoo(Localizer).Take(2).ToList();
|
||||
}
|
||||
|
||||
private Task<QueryData<Foo>> OnRefreshQueryAsync(QueryPageOptions options)
|
||||
{
|
||||
// 设置记录总数
|
||||
var total = AutoItems.Count();
|
||||
var total = AutoItems.Count;
|
||||
var foo = Foo.Generate(Localizer);
|
||||
foo.Id = total++;
|
||||
foo.Name = Localizer["Foo.Name", total.ToString("D4")];
|
||||
foo.Address = Localizer["Foo.Address", $"{random.Next(1000, 2000)}"];
|
||||
|
||||
AutoItems.Insert(0, new Foo()
|
||||
{
|
||||
Id = total++,
|
||||
Name = $"张三 {total:d4}",
|
||||
DateTime = DateTime.Now.AddDays(total - 1),
|
||||
Address = $"上海市普陀区金沙江路 {random.Next(1000, 2000)} 弄",
|
||||
Count = random.Next(1, 100),
|
||||
Complete = random.Next(1, 100) > 50,
|
||||
Education = random.Next(1, 100) > 50 ? EnumEducation.Primary : EnumEducation.Middel
|
||||
});
|
||||
AutoItems.Insert(0, foo);
|
||||
|
||||
if (AutoItems.Count > 10)
|
||||
{
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract class TablesBaseColumn : TablesBaseQuery
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="d"></param>
|
||||
/// <returns></returns>
|
||||
protected Task<string> IntFormatter(object? d)
|
||||
{
|
||||
var data = (int?)d;
|
||||
return Task.FromResult(data?.ToString("0.00") ?? "");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
protected Task CustomerButton(IEnumerable<Foo> items)
|
||||
{
|
||||
var cate = ToastCategory.Information;
|
||||
var title = "自定义按钮处理方法";
|
||||
var content = $"通过不同的函数区分按钮处理逻辑,参数 Items 为 Table 组件中选中的行数据集合,当前选择数据 {items.Count()} 条";
|
||||
ToastService?.Show(new ToastOption()
|
||||
{
|
||||
Category = cate,
|
||||
Title = title,
|
||||
Content = content
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
protected Task OnRowButtonClick(Foo item)
|
||||
{
|
||||
var cate = ToastCategory.Success;
|
||||
var title = "行内按钮处理方法";
|
||||
var content = "通过不同的函数区分按钮处理逻辑,参数 Item 为当前行数据";
|
||||
ToastService?.Show(new ToastOption()
|
||||
{
|
||||
Category = cate,
|
||||
Title = title,
|
||||
Content = content
|
||||
});
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
// Copyright (c) Argo Zhang (argo@163.com). All rights reserved.
|
||||
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
|
||||
// Website: https://www.blazor.zone or https://argozhang.github.io/
|
||||
|
||||
using BootstrapBlazor.Components;
|
||||
using BootstrapBlazor.Shared.Pages.Components;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BootstrapBlazor.Shared.Pages
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract class TablesBaseEdit : TablesBaseQuery
|
||||
{
|
||||
private static readonly object _objectLock = new();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected List<Foo> EditItems { get; set; } = GenerateItems();
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
protected IEnumerable<SelectedItem>? Educations { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// OnInitialized 方法
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
base.OnInitialized();
|
||||
|
||||
Educations = typeof(EnumEducation).ToSelectList();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="options"></param>
|
||||
/// <returns></returns>
|
||||
protected Task<QueryData<Foo>> OnEditQueryAsync(QueryPageOptions options) => FooQueryAsync(EditItems, options);
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
protected static Task<Foo> OnAddAsync()
|
||||
{
|
||||
return Task.FromResult(new Foo() { DateTime = DateTime.Now });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="item"></param>
|
||||
/// <returns></returns>
|
||||
protected Task<bool> OnSaveAsync(Foo item)
|
||||
{
|
||||
// 增加数据演示代码
|
||||
if (item.Id == 0)
|
||||
{
|
||||
// 演示代码,生产中请根据实际情况考虑是否加锁操作
|
||||
lock (_objectLock)
|
||||
{
|
||||
item.Id = EditItems.Max(i => i.Id) + 1;
|
||||
EditItems.Add(item);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var oldItem = EditItems.FirstOrDefault(i => i.Id == item.Id);
|
||||
if (oldItem != null)
|
||||
{
|
||||
oldItem.Name = item.Name;
|
||||
oldItem.Address = item.Address;
|
||||
oldItem.DateTime = item.DateTime;
|
||||
oldItem.Count = item.Count;
|
||||
oldItem.Complete = item.Complete;
|
||||
oldItem.Education = item.Education;
|
||||
}
|
||||
}
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="items"></param>
|
||||
/// <returns></returns>
|
||||
protected Task<bool> OnDeleteAsync(IEnumerable<Foo> items)
|
||||
{
|
||||
items.ToList().ForEach(i => EditItems.Remove(i));
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
}
|
||||
}
|
||||