为 blazor 创建三态复选框组件

问题描述 投票:0回答:4
checkbox blazor
4个回答
2
投票

我在 .NET core 3.1+ 中实现了这个简单的组件。 这是一个小提琴

CSS来自bootstrap,需要显示一个空框,一个选中的框和一个“满”框以指示状态0,1,-1(可以轻松更改这些值):

<style>
    [class^="icon-"], [class*=" icon-"] { display: inline-block; width: 14px; height: 14px; margin-top: 1px; *margin-right: .3em; line-height: 14px; vertical-align: text-top; background-image: url(/img/glyphicons-halflings.png); background-position: 14px 14px; background-repeat: no-repeat; }
    .bootstrap-checkbox { display: inline-block; position: relative; width: 13px; height: 13px; border: 1px solid #000; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; }
        .bootstrap-checkbox i { position: absolute; left: -2px; top: -3px; }
    .icon-stop { background-position: -312px -72px; }
    .icon-check { background-position: -288px 0px; }
</style>

这是 blazor 组件:

<div @ref=checkboxElement class="bootstrap-checkbox" @onclick="(e) => OnClick(e)"><i class="@ImgClass"></i></div>@Description

@code {

    public ElementReference checkboxElement { get; set; }
    [Parameter]
    public string Description { get; set; }
    [Parameter]
    public bool? Checked { get; set; }
    public string ImgClass { get; set; }
    public int Value { get; set; }

    protected override void OnInitialized()
    {
        Value = Checked switch { null => -1, true => 1, false => 0 };
        ImgClass = Value switch { -1 => "icon-stop", 1 => "icon-check", _ => "" };
    }

    public void OnClick(MouseEventArgs e)
    {
        switch (ImgClass)
        {
            case "":
                ImgClass = "icon-check";
                Value = 1;
                break;
            case "icon-check":
                ImgClass = "icon-stop";
                Value = -1;
                break;
            case "icon-stop":
                ImgClass = "";
                Value = 0;
                break;
        }
    }
}


1
投票

使用 JS 互操作

创建一个简单的脚本

<script>
var auxiliarDOM = auxiliarDOM || {};
auxiliarDOM.setValue = function (element, property,value) {
    element[property] = value;
}
</script>

然后在 blazor 中你可以有一个 ElementRef

@inject IJSRuntime JSRuntime
<input @ref="checkRef" type="checkbox" />

private ElementReference checkRef;

//this make the check indeterminate
await JSRuntime.InvokeVoidAsync("auxiliarDOM.setValue", checkRef, "indeterminate", true);
//this make the check no indeterminate
await JSRuntime.InvokeVoidAsync("auxiliarDOM.setValue", checkRef, "indeterminate", false);

1
投票

三态复选框组件,基于Eliseo的答案:

工作示例:Blazor fiddle

JS设置

indeterminate
属性:

<script type="text/javascript">
    function setElementProperty(element, property, value) {
        element[property] = value;
    }
</script>

CheckBox.razor 文件:

<input @ref=elementRef id="@elementId" type="checkbox" checked="@isChecked" @onchange="OnChange"/>
<label for="@elementId">@ChildContent</label>

CheckBox.razor.cs 文件:

using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System;
using System.Threading.Tasks;

public partial class CheckBox
{
    [Inject]
    IJSRuntime jsRuntime { get; set; } = null!;

    [Parameter]
    public RenderFragment? ChildContent { get; set; }

    [Parameter]
    public bool? Checked { get; set; }

    [Parameter]
    public EventCallback<bool?> CheckedChanged { get; set; }

    private bool isChecked;

    private ElementReference elementRef;

    private string elementId = Guid.NewGuid().ToString();

    private async Task OnChange(ChangeEventArgs e)
    {
        Checked = Checked switch
        {
            false => true,
            true => null,
            null => false,
        };

        isChecked = Checked != false;

        bool indet = Checked == null;

        await jsRuntime.InvokeVoidAsync("setElementProperty", elementRef, "indeterminate", indet);

        await CheckedChanged.InvokeAsync(Checked);
    }
}

0
投票

由于这篇文章帮助我制作了自己的三态复选框,我想分享我的实现,作为一个剃刀文件:

<input type="checkbox" @ref=@thisRef @bind=boundValue @bind:after=Change @attributes=AdditionalAttributes />
<script type="text/javascript">
    function setElementProperty(element, property, value) {
        element[property] = value;
    }
</script>

@code {
    private bool boundValue = false;
    private int _value = 0;
    private ElementReference thisRef = new();
    public int Value
    {
        get => _value;
        set
        {
            if (value < 0 || value > 2)
                throw new ArgumentOutOfRangeException("Value takes values of 0, 1 and 2, where 0 is false, 1 is true and 2 is indeterminate.");
            _value = value;
            if (IsIndeterminate())
                SetIndeterminate();
            else
            {
                if (_value == 1)
                    boundValue = true;
                else
                    boundValue = false;
            }
        }
    }
    public bool? ValueBool
    {
        get => Value switch
        {
            0 => false,
            1 => true,
            2 => null,
            _ => throw new Exception()
        };
        set
        {
            switch (value)
            {
                case null:
                    Value = 2; break;
                case true:
                    Value = 1; break;
                case false:
                    Value = 0; break;
            }
        }
    }
    public bool Checked 
    {    
        get => Value == 1;
        set => Value = value ? 1 : 0;
    }
    public StateEnum State
    {
        get => (StateEnum)Value;
        set => Value = (int)value;
    }
    [Parameter(CaptureUnmatchedValues = true)]
    public IDictionary<string, object>? AdditionalAttributes { get; set; }
    public bool IsIndeterminate() => _value == 2;
    private async void SetIndeterminate()
    {
        _value = 2;
        await ijs.InvokeVoidAsync("setElementProperty", thisRef, "indeterminate", true);
    }
    private void Change()
    {
        if (boundValue)
            _value = 1;
        else
            _value = 0;
    }
    public enum StateEnum
    {
        Unchecked,
        Checked,
        Indeterminate
    }
}```
© www.soinside.com 2019 - 2024. All rights reserved.