Blazor:如何将ViewModel从子组件传递到父组件,反之亦然

时间:2020-03-06 06:20:26

标签: blazor blazor-server-side blazor-client-side

如何在Blazor中将ViewModel从子组件传递到父组件,反之亦然

我正在使用MVVM模式构建Blazor应用。

尝试以下代码但不起作用

[Parameter]
public ViewModel viewModel { get; set; }

1 个答案:

答案 0 :(得分:0)

我写了一篇有关Blazor中亲子交流的博客文章。

https://datajugglerblazor.blogspot.com/2020/01/how-to-use-interfaces-to-communicate.html

我创建了一个Nuget包来简化此过程:

DataJuggler.Blazor.Components

我创建父子交流的方式是通过父组件或页面实现此IBlazorComponentParent接口:

#region using statements

using System.Collections.Generic;

#endregion

namespace DataJuggler.Blazor.Components.Interfaces
{

    #region interface IBlazorComponentParent
    /// <summary>
    /// This interface is used to host IBlazorComponent objects
    /// </summary>
    public interface IBlazorComponentParent
    {

        #region Methods

            #region FindChildByName(string name)
            /// <summary>
            /// This method is used to find a child component that has registered with the parent.
            /// </summary>
            /// <param name="name"></param>
            /// <returns></returns>
            IBlazorComponent FindChildByName(string name);
            #endregion

            #region ReceiveData(Message message)
            /// <summary>
            /// This method is used to send data from a child component to the parent component or page.
            /// </summary>
            /// <param name="data"></param>
            void ReceiveData(Message message);
            #endregion

            #region Refresh()
            /// <summary>
            /// This method will call StateHasChanged to refresh the UI
            /// </summary>
            void Refresh();
            #endregion

            #region Register(IBlazorComponent component)
            /// <summary>
            /// This method is called by the Sprite to a subscriber so it can register with the subscriber, and 
            /// receiver events after that.
            /// </summary>
            void Register(IBlazorComponent component);    
            #endregion

        #endregion

        #region Properties

            #region Children
            /// <summary>
            /// This property gets or sets the value for Children.
            /// </summary>
            public List<IBlazorComponent> Children { get; set; }
            #endregion

        #endregion

    }
    #endregion

}

然后您的子组件实现IBlazorComponent

#region using statements

using System.Collections.Generic;

#endregion

namespace DataJuggler.Blazor.Components.Interfaces
{

    #region interface IBlazorComponent
    /// <summary>
    /// This interface allows communication between a blazor componetn and a parent component or page.
    /// </summary>
    public interface IBlazorComponent
    {

        #region Methods

            #region ReceiveData(Message message)
            /// <summary>
            /// This method is used to send data from a child component to the parent component or page.
            /// </summary>
            /// <param name="data"></param>
            void ReceiveData(Message message);
            #endregion

        #endregion

        #region Properties

            #region Name
            /// <summary>
            /// This property gets or sets the Name.
            /// </summary>
            public string Name { get; set; }
            #endregion

            #region Parent
            /// <summary>
            /// This property gets or sets the Parent componet or page for this object.
            /// </summary>
            public IBlazorComponentParent Parent { get; set; }
            #endregion

        #endregion

    }
    #endregion

}

然后,在实现组件时,设置Parent = this:

<div class="galleryimages">
    @if (SelectedArtist.HasImages)
    { 
        @foreach (Image image in SelectedArtist.Images)
        {  
            <ImageButton Image=image Parent=this></ImageButton>
        }
    }
</div>

在“图像”组件上“父级”的setter属性中,我向父级注册:

private IBlazorComponentParent parent;

[Parameter]
public IBlazorComponentParent Parent
{
    get { return parent; }
    set 
    { 
       // store the parent
       parent = value;

       // if the value for HasParent is true
       if (HasParent)
       {
           // Register with the parent
           Parent.Register(this);
       }
   }

在“索引”页面上,我的Register方法如下所示:

public void Register(IBlazorComponent component)
{
    // If the component object exists
    if (NullHelper.Exists(component, Children))
    {
        // If this is the Login component
        if (component.Name == "Login")
        {
            // Set the Signup control
            this.Login = component as Login;
        }

        // add this child
        Children.Add(component);
    }
}

现在,父级和子级都具有一个ReceiveData方法,您可以在其中发送我所谓的MessageObject。

    // Create a message
    Message message = new Message();

    // Send a clear message
    message.Text = "";

    // Send data
    NamedParameter parameter = new NamedParameter();

    // set the properties and add new parameter
    parameter.Name = "MyData";
    parameter.Value = myData;
    message.Parameters.Add(parameter);
}

在接收数据方法中,读取参数并进行更新。

这是我的Blazor Image Gallery Sample项目的一个示例,我在用户登录后读取参数:

public void ReceiveData(Message message)
{
    // If the message object exists
    if (NullHelper.Exists(message))
    {
        // if a NewArtist signed up or Logged In
        if (message.Text == "Artist Logged In"
        {
            // if the parameters collection exists
            if (message.HasParameters)
            {
                // iterate the parameters                            
                foreach (NamedParameter parameter in message.Parameters)                                           
                {
                    // if this is the name
                    if (parameter.Name == "Artist")
                    {
                        // Get the login response
                        LoginResponse loginResponse = parameter.Value as LoginResponse;

                        // If the loginResponse object exists
                        if (NullHelper.Exists(loginResponse))
                        {
                            // Update the UI that we have a login
                            LoginComplete(loginResponse);
                        }
                    }
                 }
              }
            }
            else
            {
                // Set the message text
                this.Message = message.Text;

                // Update the UI
                Refresh();
            }
        }
    }

如果您要查看,这里是一个完整的项目: https://github.com/DataJuggler/BlazorImageGallery

如果您觉得无聊,这里还有一个视频:

https://youtu.be/3xKXJQ4qThQ

也许这会给你一些想法。