Blazor -绑定Blazor组件或解决方案[询问WPF人员]

sigwle7e  于 2022-11-18  发布在  其他
关注(0)|答案(2)|浏览(163)

我在WPF中为Blazor寻找这样的东西,如果可能的话:
WPF:

<ContentPresenter Content="{Binding LicensesText}" />



public LicensesText LicensesText { get; set; }

ctor()
{
    LicensesText licensesText = new LicensesText();
    licensesText.ClickedShowComparision += () => { Licenses = new Licences(); };
    LicensesText = licensesText;

    //Sleep for 5 seconds
    List<LicensesText> list = new ();
    list.Add(licensesText);

    LicensesText licensesText1 = new LicensesText();
    licensesText1.ClickedShowComparision += () => { Licenses = new Licences(); };
    LicensesText = licensesText1;

    //Sleep for 5 seconds
    LicensesText = list.First();}
}

最好的可能是这样的:

  • 你好
    SaySomething.razor
<h3>@Label</h3>

@code {

    public string Label { get; set; } = "Default Label";

    public void SetLabel(string label)
    {
        Label = label;
        StateHasChanged();
    }
}

Index.razor

@SaySometing

@code
{
    public SaySometing SaySometing { get; set; } = new SaySometing();
}

但可以肯定的是,它并不像它那样工作。
我得到了一些解决方案,但它们都是不完美的。我不知道如何可视化,例如已经创建的ComponentBase元素,如果可能的话。

@page "/"

@DynamicRender
<SaySometing @ref="SaySometing" />
<DynamicComponent Type="typeof(SaySometing)" @ref="DynamicComponent"></DynamicComponent>

<button @onclick="args => ChangeText(args)">Click Me!</button>

@code
{

    public SaySometing SaySometing { get; set; } = new SaySometing();

    public SaySometing SaySometing1 { get; set; } = new SaySometing();

    public DynamicComponent DynamicComponent { get; set; } = new DynamicComponent();

    private RenderFragment DynamicRender { get; set; }

    protected override Task OnInitializedAsync()
    {

        DynamicRender = CreateComponent();
        
        return base.OnInitializedAsync();
    }

    private RenderFragment CreateComponent() => builder =>
    {
        builder.OpenComponent(0, typeof(SaySometing));
        builder.AddComponentReferenceCapture(1, obj =>
        {
            SaySometing1 = (SaySometing) obj;
        });
        builder.CloseComponent();
    };

    private void ChangeText(MouseEventArgs args)
    {
        SaySometing.SetLabel("Hello From SaySomething!");
        SaySometing1.SetLabel("Gutten Tag From SaySomething1!");
        ((SaySometing?)DynamicComponent?.Instance)?.SetLabel("Dobrý den from DynamicComponent");
        StateHasChanged();
    }

}

这三个都能正常工作,并将文本切换到正确的SaySomething. Label。但如果我想将SaySomething 1更改为新示例,并保留旧示例,然后再次渲染它,该怎么办?或者在Blazor中如何解决这个问题。正如我所说,我是WPF的人,这对我来说是一个新的丛林。或者是这项技术中最好的解决方案。

iyr7buue

iyr7buue1#

您需要将数据及其状态从表示中分离出来。许多组件没有表现出关注点的分离:数据访问、数据管理和状态、以及数据显示都集成到一个页面中。
这可能完全离谱:如果是的话,我会删除答案。
去柜台吧。
我们可以创建一个计数器状态对象:

public class CounterState
    {
        public Guid CounterId { get; } = Guid.NewGuid();
        public int Counter { get; private set; }
        public string Name => this.CounterId.ToString().Substring(0, 4);

        public void Increment()
            => Counter++;
    }

用于管理数据的服务-在本例中为计数器对象列表:

public class CounterViewService
{
    public CounterState CounterState { get; private set; }

    public List<CounterState> Items { get; set; } = new();

    public event EventHandler? CounterChanged;

    public CounterViewService()
    {
       this.CounterState = new CounterState();
        Items.Add(this.CounterState);
    }

    public void SetCounter(CounterState item)
    { 
        this.CounterState = item;
        this.CounterChanged?.Invoke(item, EventArgs.Empty);
    }

    public void AddCounterState()
    {
        var item = new CounterState();
        this.Items.Add(item);
        this.CounterState = item;
    }
    public void Increment()
    {
        this.CounterState.Increment();
        this.CounterChanged?.Invoke(this.CounterState, EventArgs.Empty);
    }
}

注册为如下服务:

builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
builder.Services.AddScoped<CounterViewService>();
builder.Services.AddSingleton<WeatherForecastService>();

显示计数器状态的计数器组件:

@inject CounterViewService Service
@implements IDisposable

<div class="bg-dark text-white p-2 m-2">
    <h3>Counter Display @Service.CounterState.Name</h3>
    <div>Counter : @Service.CounterState.Counter</div>
    <div class="m-2">
        <button class="btn btn-light" @onclick="IncrementCount">Increment me</button>
    </div>
</div>

@code {
    protected override void OnInitialized()
        => this.Service.CounterChanged += this.OnChange;

    private void IncrementCount()
    => this.Service.Increment();

    private void OnChange(object? sender, EventArgs e)
        => this.StateHasChanged();

    public void Dispose()
        => this.Service.CounterChanged -= this.OnChange;
}

最后是显示页面:

@inject CounterViewService Service
@page "/counter"

<PageTitle>Counter</PageTitle>

<CounterDisplay />

<div class="m-2">
    <button class="btn btn-primary me-2" @onclick=this.AddCounter>AddCounter</button>
    @foreach (var counter in Service.Items)
    {
        <button class="btn btn-secondary me-2" @onclick="() => this.SelectCounter(counter)">Select Counter @(counter.CounterId.ToString().Substring(0, 4))</button>
    }
</div>

@code {
    private void AddCounter()
        => this.Service.AddCounterState();

    private void SelectCounter(CounterState counter)
        => this.Service.SetCounter(counter);
}

屏幕截图显示它的运行情况:

gkl3eglg

gkl3eglg2#

这就是我需要的...
RazorParent.razor:

//Soemthing like ContentPresenter in the WPF
< DoesExistSomethingLikeThis Content="@RazChild" />

<a @OnClick="DisplayConfiguredRazChild">...
<a @OnClick="DisplayEmptyRazChild">...

RazorParent.剃刀@代码:

RazorChildren RazChild {get;set;} = null;

void DisplayConfiguredRazChild()
{
RazorChildren razChild = new RazorChildren();
razChild.Configure();
RazChild = razChild;
StateHasChanged();
}

void DisplayEmptyRazChild()
{
RazorChildren razChild = new RazorChildren();
RazChild = razChild;
StateHasChanged();
}

或者,如果存在类似于您创建视图并在后面的代码中配置它,然后通过绑定显示它,并仍然通过创建的示例控制它......或者,您必须始终执行以下操作:

<RazorChildren @ref="_razChildRef" Param1="@RazChild.Param1"/>

不幸的是,你不能控制原始示例。有没有可能在Blazor中创建像WPF ContentPresenter这样的东西?在那里你只绑定ComponentBase示例?这将是惊人的,我知道有RenderFragment,DynamicComponent等...但没有什么可以取代这种行为,你只需要直接绑定ComponentBased组件...没有重复的引用示例和在剃刀中传递参数。

相关问题