c# - 如何从 C# 方法添加 Razor 标记?

标签 c# razor blazor .net-5

目标

我的页面上有一个表单将调用方法 OnFinish当用户点击按钮发送表单时。在那种方法中,我想向页面添加新标记。 (表格代码不相关,这里就不加了)

问题

似乎没有从 C# 代码添加 Razor 标记的简单方法(如果有的话)。

我尝试过的

我尝试的第一件事是在 C# 代码中直接标记。看起来像这样:

private void OnFinish(EditContext editContext)
{
    <a>Placeholder</a>
}

这确实 - 当然 - 不起作用,因为我是在 .cs 文件中编写的。


在 .razor 文件中,我尝试做同样的事情:

@code
{
    private void OnFinish(EditContext editContext)
    {
        <a>Placeholder</a>
    }
}

编译器也不喜欢这样并引发了以下错误:

The name '__builder' does not exist in the current context

我很快就从this中学到了问题,该标记不能写在 @code 中 block 。


根据 this官方 ASP.NET 博客文章,在 @functions 中编写标记 block 应该工作:

@functions
{
    private void OnFinish(EditContext editContext)
    {
        <a>Placeholder</a>
    }
}

不幸的是,这与使用 @code 的结果相同 block 。

编辑:再次阅读博文后我意识到,该功能仅适用于 .cshtml文件。我对此进行了测试,并且确实可以在 .cshtml 中使用文件。但是这些文件不能作为组件使用,所以对我来说终究是行不通的。


我尝试使用 RenderTreeBuilder __builder作为方法中的参数,在 this 中建议回答。

这个解决方案的问题是,__builder参数只能在标记代码中使用,如下所示:

<a>@__builder</a>

而不是来自 C# 代码(这就是使用参数的原因)。


接下来我发现的是 @helper block ,在 this 中提到回答。我将它应用到我的代码中,如下所示:

@helper OnFinish(EditContext editContext) 
{
    <a>Placeholder</a>
}

这也不起作用,因为编译器会引发以下两个错误:

The helper directive is not supported.

The name 'helper' does not exist in the current context

结论

现在,搜索到此结束。我花了很多时间研究这个,我想相信可能根本没有任何解决方案。我错过了什么?


编辑

有些人提到了将标记放在 if 中的想法,而当某些条件成立时 if 会被激活(例如,我将一个 bool 设置为 true 或我更改了一个变量并且 if 识别了这一点)。

该解决方案可以在 this 中找到其他问题或 this在当前线程中回答。

该解决方案的代码如下所示:

if (renderNewMarkup)
{
    <a>Placeholder</a>
}
@functions
{
    private void OnFinish(EditContext editContext)
    {
        renderNewMarkup = true;
    }
}

这确实有效,但我认为它非常不愉快。我遇到的问题是变量的使用。

在我的程序中,我从 UI 检索一些数据并将其进一步传递给当时创建的标记。我可以举个例子:

private void OnFinish(EditContext editContext)
{
    Dictionary<string, string> dict = new()
    {
        ["Key1"] = boundVariable,
        ["Key2"] = otherBoundVariable,
        ["Key3"] = anotherBoundVariable
    }
    
    // Create markup with dict variable
}

我想添加到 HTML 的标记是一个自定义 Razor 组件,它具有 Dictionary<string, string>参数。

您可以看到,我现在不能只是在那里简单地创建标记。我必须实现我想要的效果如下所示:

@if (renderNewCustomComponent)
{
    <Custom DictParameter="@dict" />
}

@code
{
    private Dictionary<string, string> dict;

    private void OnFinish(EditContext editContext)
    {
        dict = new()
        {
            ["Key1"] = boundVariable,
            ["Key2"] = otherBoundVariable,
            ["Key3"] = anotherBoundVariable
        }
    
        renderNewCustomComponent = true;
    }
}

我希望你明白我的意思。


那么这个解决方案还有一个更大的问题。当我想调用一个方法时,例如AddElementToHTML() ,这将始终向 HTML 添加一些元素,这是不可能的。是的,通过一些复杂的方式,使用 @foreach什么的,那是可能的,但为什么语言一开始就不允许这样做呢?

最佳答案

原始答案

这向您展示了如何从标记构建和显示一个简单的渲染片段。这可能会有所帮助。

@page "/Test"
<h3>Test8</h3>
<input @bind-value="content" class="form-control" />
<button class="btn btn-dark" @onclick="RenderSomeContent">Render Content</button>
<button class="btn btn-danger ml-2" @onclick="ClearContent">Clear Content</button>

@Placeholder

@code {
    RenderFragment Placeholder { get; set; }

    string content = "<div class='m-3 bg-success'>Hello</div>";

    void RenderSomeContent()
    {
        Placeholder = (builder) =>
        {
            builder.AddMarkupContent(0, content);
        };
    }

    void ClearContent()
    {
        Placeholder = null;
    }
}

评论更新

二进制逻辑控件
@if (this.Show)
{
    if (this.ChildContent != null)
    {
        @this.ChildContent
    }
    else
    {
        @((MarkupString)this.Body)
    }
}

@code {
    [Parameter] public bool Show { get; set; }
    [Parameter] public RenderFragment ChildContent { get; set; }
    [Parameter] public string Body { get; set; }
}
测试页面
@page "/Test"

<button class="btn btn-secondary" @onclick="DoIt">Toggle content</button>

<BinaryLogicControl Show="show">
    <div class='m-3 bg-success'>Hello</div>
</BinaryLogicControl>
<BinaryLogicControl Show="show" Body="@Display" />

@code {

    string Display = string.Empty;
    bool show;

    void DoIt()
    {
        show = !show;
        Display = "<div class='m-5 p-3 bg-danger'>Hello</div>";
    }
}

基于渲染组件的更新

根据评论,您想要的是 Net 6 中的 DynamicComponent。目前您必须构建自己的(更简单的)版本。下面的代码显示了原始答案的更新版本,它构建了用于呈现的 BinaryLogicControl 而不是简单的 Markupstring

@page "/Test"

<button class="btn btn-primary" @onclick="RenderMe">Render Control</button>

@Placeholder

@code {
   RenderFragment Placeholder { get; set; }

    void RenderMe()
    {
        RenderSomeContent(typeof(BinaryLogicControl), new Dictionary<string, object> { 
           { "Show", true }, 
           { "Body", "<div class='m-3 bg-warning'>Hello</div>" }
        });
    }

    void RenderSomeContent(Type componentType, Dictionary<string, object> parameters)
    {
        Placeholder = (builder) =>
        {
            builder.OpenComponent(0, componentType);
            foreach (var parameter in parameters)
            {
                builder.AddAttribute(1, parameter.Key, parameter.Value);
            }
            builder.CloseComponent();
        };
    }

关于c# - 如何从 C# 方法添加 Razor 标记?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68631908/

相关文章:

c# - 查看文件是否包含特定字符串,然后读取该行

.net-core - 如何在 Blazor WebAssembly 中使用 Roslyn 创建 CSharpCompilation?

c# - blazor wasm 应用程序中运行时的程序集构建版本

c# - 从局部 View 设置主 url 的路由值

C#:设计一个更快的断言函数,仅在触发时格式化错误字符串

javascript - 按条件显示 kendo UI TreeView 的上下文菜单

html - 在 MVC 中使用 Metro CSS 3 表单验证

c# - Blazor 获取 div 位置/坐标

c# - ASP.NET Core - 提供静态文件

c# - 未经验证的 MVC 自定义模型注释