Blazor 服务器端组件 - 绑定未更新

从后面的代码更新绑定属性不会更新显示的 SVG,但是更改输入中的值会更新。如何从背后的代码更改绑定属性并触发对 UI 上的 SVG 的重绘。

@page "/svg"
@using System.Timers

<h3>SVG Test</h3>

<div>
    <input type="text" @bind-value="X1"/>
    <input type="text" @bind-value="Y1"/>
    <input type="text" @bind-value="X2"/>
    <input type="text" @bind-value="Y2"/>
    
    <svg width="500" height="300">
        <line x1="@X1" y1="@Y1" x2="@X2" y2="@Y2" style="stroke:red;stroke-width:5"/>
    </svg>
</div>

@code {
    public int X1 { get; set; }
    public int Y1 { get; set; }
    public int X2 { get; set; }
    public int Y2 { get; set; }

    protected override void OnInitialized()
    {
        X1 = 25;
        Y1 = 25;
        X2 = 200;
        Y2 = 200;

        var timer = new Timer(1000){AutoReset = true};
        timer.Elapsed += (sender,args) =>
        {
            Console.WriteLine("Elapsed");
            X2 -= 5;
            StateHasChanged();
        };
        timer.Start();
    }
}

在上面的代码中

  • 我可以确认计时器正在触发(控制台中的 Elapsed 消息)。
  • 如果我更改输入框中的值(即 X1),然后将焦点更改为另一个元素(输入),则 X2 的值(已更改)也会更新(更改为应该基于数字的值)已触发的已过事件)。
  • 此外,当更改的输入失去焦点时,SVG 中的行也会相应更改。

如何让它从背后的代码中刷新而不是改变元素焦点。我认为这就是 StateHasChanged() 的用途。

ii328397830 回答:Blazor 服务器端组件 - 绑定未更新

找到答案:

因为计时器在与 UI 不同的线程上运行,StateHasChanged() 需要在 UI 线程上运行才能更新。

代替:

StateHasChanged();

改为:

InvokeAsync(StateHasChanged); // execute on the UI thread

为了乐趣和任何感兴趣的人而完成的工作演示,在 SVG 的外部(25px 填充)周围走线:

@page "/svg"
@using System.Timers

<h3>SVG Test</h3>

<div>
    <input type="text" @bind-value="X1"/>
    <input type="text" @bind-value="Y1"/>
    <input type="text" @bind-value="X2"/>
    <input type="text" @bind-value="Y2"/>

    <svg width="300" height="300">
        <line x1="@X1" y1="@Y1" x2="@X2" y2="@Y2" style="stroke:red;stroke-width:5"/>
    </svg>
</div>

@code {
    public int X1 { get; set; }
    public int Y1 { get; set; }
    public int X2 { get; set; }
    public int Y2 { get; set; }

    protected override void OnInitialized()
    {
        base.OnInitialized();

        X1 = 25;
        Y1 = 25;
        X2 = 25;
        Y2 = 275;

        const double interval = (double) 1000 / 60;
        var timer = new Timer(interval) {AutoReset = true};
        timer.Elapsed += (sender,args) =>
        {
            Console.WriteLine("Elapsed");
            // Added this for demo purposes
            switch (X1)
            {
                case >= 25 and < 275 when Y1 == 25 && X2 == 25 && Y2 == 275: X1+=5; break;
                case 275 when Y1 == 25 && X2 == 25 && (Y2 is <= 275 and > 25): Y2-=5; break;
                case 275 when (Y1 is >= 25 and < 275) && X2 == 25 && Y2 == 25: Y1+=5; break;
                case 275 when Y1 == 275 && (X2 is >= 25 and < 275) && Y2 == 25: X2+=5; break;
                case <= 275 and > 25 when Y1 == 275 && X2 == 275 && Y2 == 25: X1-=5; break;
                case 25 when Y1 == 275 && X2 == 275 && Y2 is >= 25 and < 275: Y2+=5; break;
                case 25 when (Y1 is <= 275 and > 25) && X2 == 275 && Y2 == 275: Y1-=5; break;
                case 25 when Y1 == 25 && X2 is <= 275 and > 25 && Y2 == 275: X2-=5; break;
            }
            // Actual fix for original question
            InvokeAsync(StateHasChanged);
        };
        timer.Start();
    }
}
本文链接:https://www.f2er.com/1442.html

大家都在问