Nelze Přesunout Divs v Blazor

0

Otázka

Mám Blazor Server Aplikace s následujícími tagy DIV

<div class=mainScreen id="outerBox" style="width:@(TotalWidth)px;height:@(TotalHeight)px;">
    foreach(Device thisDevice in MyDevices)
    {
      <div class=column id="@MainDiv" style="width:@(thisDevice.Width)px;height:@(thisDevice.Height)px;left:@thisDevice.XCoordinate;top:@thisDevice.YCoordinate">
        Main Content Here...
      </div>
    }
    </div>

Pokusil jsem se nastavit Výška, Šířka, a X/Y souřadnic pomocí ukázky kódu z této stránky - https://blazor.tips/blazor-how-to-ready-window-dimensions/ ale, který nikdy nepracoval a jednoduše hodil nezachycená výjimka, bez ohledu na to, kde jsem se umístil Zkusit... bloky.

Pak jsem se přestěhoval do více jednoduchých JS volání:

 await Task.Run(async () =>
 {
  //Commenting out the OnInitializeAsync makes no difference but needs to be commented out when embedded
  //On the main component
  await this.OnInitializedAsync();
  string data = await JSRuntime.InvokeAsync<string>("getMyWindow", new object[] { });
  JObject offsets = (JObject)JsonConvert.DeserializeObject(data);
  TotalHeight = offsets.Value<int>("height");
  TotalHeight = offsets.Value<int>("width");
}

//In my JS file, the function looks as follows:
function getMyWindow() {
    var obj = {};
    obj.width = window.width;
    obj.height = window.height;
    return JSON.stringify(obj);
}

Když jsem tento volat přímo v kódu, nic se nestane - i s OnInitializeAsync komentoval.

var result = SetDimensions().Result;

Kdybych místo této metody v OnAfterRendor metoda:

protected override void OnAfterRender(bool firstRender)
{
    if (firstRender)
    {
        if (!SetTheDivs)
            SetTheDivs = SetDimensions().Result;

        StateHasChanged();
    }
}
 
protected override void OnInitialized()
{
   base.OnInitialized();
   this.OnAfterRender(true);
}

vše, co visí, dokud jsem zabít projektu. Tam se nikdy žádné chyby, ale kód nikdy se spouští, když jsem místo zarážky na výšku nebo šířku prohlášení.

Dokonce jsem přidal v Asynchronní verzi bezvýsledně:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    if (firstRender)
    {
        await SetDimensions();

        StateHasChanged();
    }
}

protected override async Task OnInitializedAsync()
{
    await this.OnAfterRenderAsync(true);
}

Stejný výsledek jako všechno visí. Jsem v rozpacích, jak postupovat a já se opravdu mohl použít nějakou pomoc!

Jako bod jasnosti, to je volání JS, že výsledky v hang:

string data = await JSRuntime.InvokeAsync<string>("getMyWindow", new object[] { });

Přidal jsem v nějaké upozornění, ale nikdy spustit:

function getMyWindow() {
    var obj = {};
    alert("hi");
    obj.width = screen.width;
    obj.height = screen.height;
    alert("ho");
    return JSON.stringify(obj);
}

Děkuji za váš čas!

BTW - já jsem změnit double čekají string data = JSRuntime.InvokeAsync<string>("getMyWindow", new object[] { }).Result;

UPDATE: přesunul jsem JS volání mimo čekají úplně a mám chybu:

InvalidOperationException: JavaScript volání interop nemůže být vydáno v této době. To je proto, že součástí je staticky vykreslen. Když předběžného načítání je povoleno, JavaScript interop volání mohou být provedena pouze v OnAfterRenderAsync životního cyklu metoda.

V tomto případě jsem doslova volá metodu z OnAfterRenderAsync metoda:

protected override async Task OnAfterRenderAsync(bool firstRender)
{
    await base.OnInitializedAsync();
    if (firstRender)
    {
        await SetDimensions();

        StateHasChanged();
    }
}

blazor c# javascript razor
2021-11-24 02:16:17
1

Nejlepší odpověď

1

Nejste si jisti, co chcete... Zkopírujte níže uvedený kód a spustit jej, a řekněte nám, jestli to je to, co jste se snaží dostat.

Index.břitva

@page "/"

<div class=mainScreen id="outerBox" style="width:@($"{TotalWidth}px");height:@($"{TotalHeight}px"); background-color: green; top:60px; position:absolute">
    @foreach (Device device in devices)
    {
    <div class=column style="width:@($"{device.Width}px");height:@($"{device.Height}px");margin-left:@($"{device.Left}px");margin-top:@($"{device.Top}px"); background-color:aliceblue">
       @device.Name: Main Content Here...
    </div>
    }
</div>

@code {
    private int TotalWidth = 520;
    private int TotalHeight = 530;

    private IList<Device> devices = Enumerable.Range(1, 5).Select(i => new Device { Name = $"Name {i}", Width = 520, Height = 100, Left = 0, Top = 5 }).ToList();

    public class Device
    {
        public string Name { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public int Left { get; set; }
        public int Top { get; set; }
    }
}

Poznámka: OnInitialized{Async} pár metod, které jsou život-cyklus metody základní třídy ComponentBase. Jsou automaticky volány Blazor rámec, když Břitva složka je vytvořena. Jsou provedeny pouze jednou. Můžete přepsat je, a přidat své logiky, ale nikdy volat ručně z vašeho kódu.

To:

protected override async Task OnInitializedAsync()
{
    await this.OnAfterRenderAsync(true);
} 

Je to špatně a nesmí být nikdy provedeno. Neměli byste zavolat OnAfterRender{Async}. To je Blazor rámec, který by měl zavolat OnAfterRender{Async},, ne developer. Mohl byste se pokusit pochopit, co váš kód dělá...

Snažte se pochopit, že když Břitva komponenty jsou definovány jako C# tříd, které jsou zvláštní případy Tříd, které vyžadují zvláštní zacházení na základě rámcové...

Aktualizace

Ken Tola, následující kód věřím, že dělá to, co hledáte. To čte šířka a výška okna objektu, předat Index component, a přemístit vaše drahá divs. Všimněte si, že předtím, než aplikace přemístí do div, jsem zkontrolovat hodnoty šířky a výšky, a zjistit rozměry divs. Je to samozřejmě dělá pro demonstrační účely, a můžete změnit tyto hodnoty, jak si přejete...

Index.břitva

@page "/"
    
@implements IDisposable
@inject IJSRuntime JSRuntime

    
<div class=mainScreen id="outerBox" style="width:@($" {TotalWidth}px");height:@($"{TotalHeight}px"); background-color: green; top:60px; position:absolute">
    @foreach (Device device in devices)
    {
        <div class=column style="width:@($" {device.Width}px");height:@($"{device.Height}px");margin-left:@($"{device.Left}px");margin-top:@($"{device.Top}px"); background-color:aliceblue">
            @device.Name: Main Content Here...
        </div>
    }
</div>

@code
{

    private DotNetObjectReference<BrowserService> objRef;
    private BrowserService BSS;

    private int TotalWidth; 
    private int TotalHeight; 

    private IList<Device> devices = Enumerable.Range(1, 5).Select(i => new Device { Name = $"Name {i}", Width = 520, Height = 100, Left = 0, Top = 5 }).ToList();

    public class Device
    {
        public string Name { get; set; }
        public int Width { get; set; }
        public int Height { get; set; }
        public int Left { get; set; }
        public int Top { get; set; }
    }
      
    protected override void OnInitialized()
    {
        BSS = new BrowserService();

        objRef = DotNetObjectReference.Create(BSS);

        BSS.Notify += OnNotify;
    }
    
    public void Dispose()
    {
        BSS.Notify -= OnNotify;

        objRef?.Dispose();
    }

    public async Task OnNotify()
    {
        // Note that the notifier only notify your component 
        // that data is ready, and that the dimensions are read
        // from a property. You can instead define event handler
        // that pass the data in the form of EventArgs... 
        TotalWidth = BSS.Dimension.Width >= 877 ? 520 : 550;
        TotalHeight = BSS.Dimension.Height >= 550 ? 800 : 1200;
    
        await InvokeAsync(() => StateHasChanged());
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        // This code is excuted only once, in order to initialize
        // the JavaScript objects
        if (firstRender)
        {
            await JSRuntime.InvokeAsync<object> 
                  ("myJsFunctions.getDimensions", objRef);
                
        }
    }

}

BrowserService.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;
using Microsoft.JSInterop;

 public class BrowserService
    {
        public event Func<Task> Notify;
#nullable enable
        public Dimension? Dimension { get; set; }
#nullable disable

        [JSInvokableAttribute("GetDimensions")]
        public async Task GetDimensions(string dimension)
        {
            JsonSerializerOptions options = new(JsonSerializerDefaults.Web)
            {
                WriteIndented = true
            };
            var _dimension = System.Text.Json.JsonSerializer.Deserialize(dimension, typeof(Dimension), options);
            Dimension = (Dimension)_dimension;

            if (Notify != null)
            {
                await Notify?.Invoke();
            }
        }
    }
    public class Dimension
    {
        public int Width { get; set; }
        public int Height { get; set; }

    }
}

Spuštění.ConfigureServices

services.AddScoped<BrowserService>();

_Host.cshtml

<script src="_framework/blazor.server.js"></script>

<script type="text/javascript">
    window.myJsFunctions = {

        getDimensions: function (dotnetHelper) {
            var dimension = {
                 width: window.innerWidth,
                 height: window.innerHeight
            };
            var json = JSON.stringify(dimension);

            return dotnetHelper.invokeMethodAsync('GetDimensions', json);
        }
    };
</script>

Poznámka: Zvážit, manipulace přemístění prvky div, když změníte velikost okna. To by mělo být citlivé, že ? Nejste si jisti, že ve vašem případě můžete použít media query. Každý, jak,, jak můžete vidět, navrhl jsem kód tak, že bere v úvahu, že vaše prvky div, může být potřeba přemístit znovu a znovu, tak to neustále (při změně velikosti) oznámí své Index component měnící rozměry. Myslím, že tohle si zaslouží novou otázku.....

2021-11-30 07:13:33

Děkuji za vaši odpověď! Já jsem prostě se snaží získat okna výšky a šířky a pak použít tyto, aby se pohybovat div panely na jejich správné umístění na obrazovce. Mohu snadno spustit metodu jako tlačítko, klepněte ale i s StateHasChanged ceně, Div se nepohybují, A to není to, co musím udělat. Já se jednoduše snažím číst celková šířka/výška k dispozici, a používat to, aby aktivně nastavit X,Y, výška, šířka, než se všechno generuje.
Ken Tola

Projel jsi můj kód ? Ne, to jsi neudělal.
enet

Úkol.Run() prohlášení byl kořen všech mých problémů! Když jsem naposledy kódované, to byl preferovanou cestu vpřed spustit synchronní kód uvnitř metody, které vyžaduje asynchronní metody - ne, že se zdá být jen pomocí asynchronní dutin. Děkuji moc! Finální kód běží v pohodě přímo z OnAfterRenderAsync.
Ken Tola

V jiných jazycích

Tato stránka je v jiných jazycích

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................