简体   繁体   English

如何在 Blazor 中通过 @Ref 获得的 Reference 设置组件属性

[英]How in Blazor Set component properties through a Reference that obtained by @Ref

I have a component that I set a reference of it in a page variable:我有一个组件,我在页面变量中设置了它的引用:

<BlazorWebFormsComponents.Button OnClick="@((args) => btnForms_Clicked(formsButton, args))" @ref="formsButton" Text="Forms Button" CssClass="btn btn-primary">
    
</BlazorWebFormsComponents.Button>

In the event handler I Set a button property (Text):在事件处理程序中,我设置了一个按钮属性(文本):

Button formsButton;

public void btnForms_Clicked(object sender, MouseEventArgs e)
{                        
    if (sender is Button)
        (sender as Button).Text = "Good Bye";
}

For most of the Button properties this code is not working, For BackColor works but for Text not.对于大多数 Button 属性,此代码不起作用,对于 BackColor 有效,但对于 Text 无效。 Also blazor makes the assignment line, a green Underlined and says "Component parameter "zzz" should not be set outside of its component", So why Blazor provides a @Ref while most of the referenced properties can not be set? blazor 也做了分配线,绿色下划线并说“组件参数“zzz”不应该设置在其组件之外”,那么为什么 Blazor 提供了一个 @Ref 而大多数引用的属性都无法设置? or is there a way to make this work?还是有办法使这项工作?

I'm not an export on Blazor, but ran into this as well.我不是 Blazor 的出口,但也遇到了这个问题。 You can do this by binding to a property on the page.您可以通过绑定到页面上的属性来做到这一点。

<BlazorWebFormsComponents.Button OnClick="@((args) => btnForms_Clicked(formsButton, args))" @ref="formsButton" Text="@ButtonText" CssClass="btn btn-primary">

</BlazorWebFormsComponents.Button>

@code{
    private string ButtonText { get; set; } = "Forms button";

    public void btnForms_Clicked(object sender, MouseEventArgs e)
    {
        ButtonText = "Good bye";
    }
}

I have never used the @Ref and don't yet know how or when to use it.我从未使用过@Ref,也不知道如何或何时使用它。

The warning is there because setting [Parameter] properties from code can cause the render tree to get out of sync, and cause double rendering of the component.出现警告是因为从代码中设置[Parameter]属性会导致渲染树不同步,并导致组件的双重渲染。

If you need to set something from code, you can expose a public method eg SetText on the component class, which does that for you.如果您需要从代码中设置某些内容,您可以在组件 class 上公开一个公共方法,例如SetText ,它会为您执行此操作。

Internally, the component [Parameter] should reference a local variable.在内部,组件[Parameter]应该引用一个局部变量。

string _text;
[Parameter] 
public string Text { get => _text; set => SetText(value);}
public void SetText(string value)
{
  _text = value;
}

I am not promoting this approach, I prefer to use the approach in @Pidon's answer.我不是在推广这种方法,我更喜欢在@Pidon 的回答中使用这种方法。 Additionally, you could consider - maybe you have too many parameters and should consider an Options parameter to consolidate此外,您可以考虑 - 也许您有太多参数,应该考虑使用 Options 参数来合并

<Button OnClick="@((args) => btnForms_Clicked(formsButton, args))" @ref="formsButton" Text="Forms Button" CssClass="btn btn-primary">

Your Button component should be defined as follows:您的 Button 组件应定义如下:

@code
{
    [Parameter]
    public EventCallback<MouseEventArgs> OnClick {get; set;} 
    [Parameter]
    public string Text {get; set;} 

}

The above code define two parameter properties that should be assigned from the Parent component.上面的代码定义了两个应该从 Parent 组件分配的参数属性。 The parent component is the component in which the Button component is instantiated.父组件是Button组件被实例化的组件。 Note that you should set the above properties from the parent component as attribute properties... you must not set them outside of the component instantiation.请注意,您应该将父组件的上述属性设置为属性属性......您不能在组件实例化之外设置它们。 Right now it's a warning, but Steve Anderson has already sad that it is going to be a compiler error soon.现在这是一个警告,但史蒂夫安德森已经很难过它很快就会成为编译器错误。 This is how you instantiate your component in the parent component:这是在父组件中实例化组件的方式:

Parent.razor父.razor

<Button OnClick="@((args) => btnForms_Clicked(args))" @ref="formsButton" 
      Text="_text" CssClass="btn btn-primary">
    
</Button>

@code
{
private Button formsButton;

// Define a local variable wich is bound to the Text parameter
private string _text = "Click me now...";

public void btnForms_Clicked( MouseEventArgs e)
{                        
    _text = "You're a good clicker.";
}
}

Note: When you click on the Button component a click event should be raised in the Button component, and the button component should propagate this event to the parent component;注意:当您点击 Button 组件时,应在 Button 组件中引发单击事件,并且按钮组件应将此事件传播到父组件; that is to execute the btnForms_Clicked method on the parent component, Here's how you do that:也就是在父组件上执行 btnForms_Clicked 方法,你可以这样做:

Button.razor按钮.razor

<div @onclick="InvokeOnClick">@Text</div>

@code
    {
        [Parameter]
        public EventCallback<MouseEventArgs> OnClick {get; set;} 
        [Parameter]
        public string Text {get; set;} 

        private async Task InvokeOnClick ()
        {
             await OnClick.InvokeAsync(); 
        }
    
    } 

Note that in order to demonstrate how to raise an event in the Button component, and propagate it to the parent component, I'm using a div element, but you can use a button element, etc.请注意,为了演示如何在 Button 组件中引发事件并将其传播到父组件,我使用的是 div 元素,但您可以使用按钮元素等。

@onclick is a compiler directive instructing to create an EventCallback 'delegate' whose value is the event handler InvokeOnClick . @onclick是一个编译器指令,指示创建一个 EventCallback 'delegate',其值为事件处理程序InvokeOnClick Now, whenever you click on the div element, the click event is raised, and the event handler InvokeOnClick is called... from this event we execute the EventCallback 'delegate' OnClick ;现在,每当您单击 div 元素时,都会引发click事件,并调用事件处理程序InvokeOnClick ...从该事件中我们执行 EventCallback 'delegate' OnClick in other words, we call the btnForms_Clicked method defined in the parent component.换句话说,我们调用父组件中定义的 btnForms_Clicked 方法。

So what the @ref directive is good for?那么@ref指令有什么用呢? You may use the @ref directive to get a reference to a component that contain a method you want to call from its parent component: Suppose you define a child component that serves as a dialog widget, and this component define a Show method, that when is called, display the dialog widget.您可以使用@ref 指令来获取对包含要从其父组件调用的方法的组件的引用:假设您定义了一个用作对话框小部件的子组件,并且该组件定义了一个Show方法,当被调用,显示对话框小部件。 This is fine and legitimate, but never try to change or set parameter properties outside of the component instantiation.这很好且合法,但切勿尝试在组件实例化之外更改或设置参数属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从@ref 组件引用调用方法时,Blazor 绑定不起作用 - Blazor binding is not working when calling a method from @ref component reference 将 @ref 添加到循环中的 Blazor 组件 - Add @ref to a Blazor component in a loop 如何使用 RenderTreeBuilder 绑定对 blazor 中组件的引用? - How to bind a reference to a component in blazor using the RenderTreeBuilder? 如何将 blazor 组件设置为单一渲染? - How to set a blazor component to single render? 如何在 Blazor(子)组件中引用“@typeparam TModel”字段? - How can I reference a "@typeparam TModel" field in the Blazor (sub)-component? 如何通过变量引用修改控件属性 - How to modify control properties through variable reference Blazor 组件参考 Null 首次渲染 - Blazor Component Reference Null on First Render 如何使用DataContractJsonSerializer使用从Web(以JSON形式)获取的数据设置对象属性的子集 - How to set a subset of properties of an object using data obtained from web (in form of JSON) using DataContractJsonSerializer 如何迭代有限的实例属性集? - How to iterate through limited set of instance properties? Blazor WASM 应用程序中的 Object 参考未设置错误 - Object reference not set error in Blazor WASM app
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM