Bootstrap Blazor UI 庫小技巧 (持續(xù)更新)
1. 文本處理鍵盤按鍵
<Bootstrap Blazorclass="table-toolbar-search" placeholder="@SearchPlaceholderText" @onkeyup="OnSearchKeyUp" @bind-Value="@SearchText">
</BootstrapInput>
@code{
private async Task OnSearchKeyUp(KeyboardEventArgs args)
{
if (args.Key == "Enter")
{
await SearchClick();
}
else if (args.Key == "Escape")
{
await ClearSearchClick();
}
}
}
2. 文本框逐字搜索
UseInputEvent: 是否在文本框輸入值時觸發(fā) bind-value:event="oninput" 默認(rèn) false
<BootstrapInput @bind-Value="value" ShowLabel="true" UseInputEvent="true" />
@value
@code{
[DisplayName("條碼文字")]
private string? value { get; set; } = "12345";
}
3. Ajaxs 請求處理參數(shù)大小寫
private async Task ProcessResponse(string userName, string password)
{
var option = new AjaxOption()
{
Url = "/api/Login",
Data = new User() { UserName = userName, Password = password }
};
var result = await AjaxService.InvokeAsync(option);
if (result == null)
{
ResultMessage = "Login failed";
}
else
{
if (200 == result.RootElement.GetProperty("code").GetInt32())
{
await SwalService.Show(new SwalOption() { Content = "Login success!", Category = SwalCategory.Success });
}
else
{
await SwalService.Show(new SwalOption() { Content = $"Login failed: {result.RootElement.GetProperty("message").GetString()}", Category = SwalCategory.Error });
}
}
}
class User
{
[JsonPropertyName("uSErnaMe22222")]
public string? UserName { get; set; }
public string? Password { get; set; }
}

4. 文本框獲取焦點(diǎn)事件(觸摸屏應(yīng)用)
<BootstrapInput ShowLabel="true"
@bind-Value="@one"
@onfocus="_=>OnFocus(0)"/>
<BootstrapInput ShowLabel="true"
@bind-Value="@two"
@onfocus="_=>OnFocus(1)"/>
<Button class="m-1" Text="abc" Color="Color.Success" OnClick='_=>OnKeyBoardsItemClick("abc")' />
<Button class="m-1" Text="def" Color="Color.Success" OnClick='_=>OnKeyBoardsItemClick("def")' />
@code{
string one="one";
string two = "two";
int mode;
private Task OnFocus(int v)
{
mode = v;
return Task.CompletedTask;
}
//觸摸按鈕點(diǎn)擊
private Task OnKeyBoardsItemClick(string v)
{
switch (mode)
{
case 1:
two = v;
break;
default:
one = v;
break;
}
return Task.CompletedTask;
}
}

5. 模板取消鏈接默認(rèn)點(diǎn)擊事件
模板默認(rèn)帶了鏈接 <a href="#" 導(dǎo)致點(diǎn)擊后回到主頁, 如果要停留在當(dāng)前頁,需要取消事件的默認(rèn)行為
https://www.jianshu.com/p/c933de9249c7
<Logout>
<LinkTemplate>
<a @onclick="@(e => IsOpen = !IsOpen)" @onclick:stopPropagation><i class="fa-solid fa-cog"></i>設(shè)置</a>
</LinkTemplate>
</Logout>
6. Segmented 超出寬度顯示滾動條
<Segmented TValue="Dto" Items="@Items" class="over-x-bar-thin" />
.over-x-bar-thin {
width: 100%;
scrollbar-width: thin;
overflow-x: auto;
}
7. 制作無軟鍵盤彈出焦點(diǎn)的輸入框
<BootstrapInput inputmode="none"/>
8. 關(guān)閉點(diǎn)擊表格行自定義操作按鈕欄冒泡事件, 避免點(diǎn)擊行事件執(zhí)行
點(diǎn)擊 PopConfirmButton 按鈕不觸發(fā) OrderListItemClick
點(diǎn)擊 Button 按鈕不觸發(fā) OrderListItemClick
<Table OnClickRowCallback="OrderListItemClick">
<TableColumns>
<TableColumn>
<Template>
<div @onclick:stopPropagation="true">
<PopConfirmButton />
<Button />
</div>
</Template>
</TableColumn>
</TableColumns>
</Table>
9. 屏幕鍵盤組件技巧
BootstrapInput 綁定變量 int?, 這樣沒有默認(rèn)值,比較清爽
不能帶 FormatString , 不然會一直格式化,表現(xiàn)很糟糕
public int? PurchasePlan { get; set; }
<OnScreenKeyboard ClassName="virtualkeyboard" Option="Option1" />
<BootstrapInput @bind-Value="v.Row.PurchasePlan" class="virtualkeyboard" data-kioskboard-type="numpad" style="max-width:70px;" />
@code{
static Dictionary<string, string> keys1 = new Dictionary<string, string>() { { "0", "." } };
static List<Dictionary<string, string>> keysArray = new List<Dictionary<string, string>>() { keys1 };
KeyboardOption Option1 = new KeyboardOption()
{
keysArrayOfObjects = keysArray,
keysFontFamily = "Barlow",
keysFontWeight = "800",
keysAllowSpacebar=false
};
}
遇到需要輸入小數(shù)情況,可以拆分為兩個輸入框分別綁定 int? 類型輸入整數(shù)和小數(shù),代碼再合并數(shù)值.
@{
var pricePurchase = (v.Row as ResProductsPro).PricePurchase;
int? p1=null;
int? p2 = null;
if (v.Row.PricePurchasePlan == null && pricePurchase != 0)
{
p1 = (int)Math.Truncate(pricePurchase);
p2 = (int)((pricePurchase - Math.Truncate(pricePurchase)) * 100);
}
}
<BootstrapInput @bind-Value="v.Row.PricePurchasePlan" PlaceHolder="@p1.ToString()" class="virtualkeyboard" data-kioskboard-type="numpad" style="max-width:50px;" />
<BootstrapInputGroupLabel DisplayText="." />
<BootstrapInput @bind-Value="v.Row.PricePurchasePlan2" PlaceHolder="@p2.ToString()" class="virtualkeyboard" data-kioskboard-type="numpad" style="max-width:50px;" />
@code{
if (item.PricePurchasePlan != null || item.PricePurchasePlan2 != null)
{
item.PricePurchase = ((item.PricePurchasePlan ?? 0) + (item.PricePurchasePlan2 ?? 0) / 100);
}
}
10. JS組件
使用bb封裝的js組件 JSModuleAutoLoader 可以達(dá)到事半功倍的效果,例如實(shí)現(xiàn)一個跟webview2交互
HybridMessage.razor
@namespace AmeTouch.Component
@inherits BootstrapModuleComponentBase
<span id="webMessageId" data="@Id" />
HybridMessage.razor.cs
[JSModuleAutoLoader("./_content/JovenRes.Shared/Component/HybridMessage.razor.js", JSObjectReference = true)]
public partial class HybridMessage
{
protected override Task InvokeInitAsync() => InvokeVoidAsync("init", Id, Interop);
[JSInvokable]
public Task<string> WebMessage(string command, string arg)
{
return Task.FromResult("OK");
}
}
HybridMessage.razor.js
import Data from "../../BootstrapBlazor/modules/data.js"
export function init(id, invoke) {
const _invoke =invoke
Data.set(id, _invoke)
}
window.webMessage = function (cmd, message) {
const id = document.getElementById('webMessageId').getAttribute('data')
const invoke = Data.get(id)
invoke.invokeMethodAsync('WebMessage', cmd, message)
.then(data => {
console.log(data);
});
}
export function dispose(id) {
const invoke = Data.get(id)
Data.remove(id)
}
wpf webview2交互
public MainWindow()
{
InitializeComponent();
this.StateChanged += async (s, e) => await MainWindow_StateChangedAsync();
private async Task MainWindow_StateChangedAsync()
{
await webView.ExecuteScriptAsync($"webMessage('windowStateChanged','{this.WindowState}')");
}
}
11. Table綁定二級類
public class Foo
{
[Key]
[Display(Name = "主鍵")]
[AutoGenerateColumn(Ignore = true)]
public int Id { get; set; }
[NotNull]
public Foo2? Foo2 { get; set; }
}
public class Foo2
{
[AutoGenerateColumn(Order = 10, Filterable = true, Searchable = true, Sortable=true)]
[Display(Name = "姓名2")]
public string? Name2 { get; set; } = "fjhfgjhf";
}
public override Task<QueryData<TModel>> QueryAsync(QueryPageOptions options)
{
...
Items = Foo.GenerateFoo((IStringLocalizer<Foo>)Localizer).Cast<TModel>().ToList();
...
System.Console.WriteLine($"排序列 {options.SortName} {options.SortOrder}");
foreach (var filter in options.Filters)
{
var actions = filter.GetFilterConditions();
if (actions.Filters != null)
{
foreach (var filter2 in actions.Filters)
{
System.Console.WriteLine($"過濾列 {filter2.FieldKey} => {filter2.FieldValue}");
}
}
}
...
}
public static List<Foo> GenerateFoo(IStringLocalizer<Foo> localizer, int count = 80) => Enumerable.Range(1, count).Select(i => new Foo()
{
Id = i,
Foo2 = new()
}).ToList();
<Table TItem="Foo" EditDialogShowMaximizeButton="true"
IsPagination="true" PageItemsSource="@PageItemsSource" DataService="@CustomerDataService"
IsStriped="true" IsBordered="true" IsMultipleSelect="true" AutoGenerateColumns="false"
ShowToolbar="true" ShowExtendButtons="true" ShowSkeleton="true"
ShowSearch
ShowAdvancedSearch>
<TableColumns>
<TableColumn Field="@context.Foo2"
Ignore="false"
FieldName="Foo2.Name2"
Text="復(fù)雜綁定"
Filterable="true"
Searchable="true"
Sortable="true">
<FilterTemplate>
<StringFilter/>
</FilterTemplate>
</TableColumn>
</TableColumns>
</Table>

注意: 如果不加 <FilterTemplate> 會顯示這樣

關(guān)聯(lián)項(xiàng)目
FreeSql QQ群:4336577
BA & Blazor QQ群:795206915
Maui Blazor 中文社區(qū) QQ群:645660665
知識共享許可協(xié)議
本作品采用 知識共享署名-非商業(yè)性使用-相同方式共享 4.0 國際許可協(xié)議 進(jìn)行許可。歡迎轉(zhuǎn)載、使用、重新發(fā)布,但務(wù)必保留文章署名AlexChow(包含鏈接: https://github.com/densen2014 ),不得用于商業(yè)目的,基于本文修改后的作品務(wù)必以相同的許可發(fā)布。如有任何疑問,請與我聯(lián)系 。
轉(zhuǎn)載聲明
本文來自博客園,作者:周創(chuàng)琳 AlexChow,轉(zhuǎn)載請注明原文鏈接:http://www.rzrgm.cn/densen2014/p/17893164.html
AlexChow
今日頭條 | 博客園 | 知乎 | Gitee | GitHub


浙公網(wǎng)安備 33010602011771號