Blazor:如何将 ViewModel 从子组件传递到父组件,反之亦然
Blazor : How to pass ViewModel from Child Component to Parent Component and vice versa
如何在 Blazor 中将 ViewModel 从子组件传递到父组件,反之亦然
我正在使用 MVVM 模式构建 Blazor 应用程序。
尝试了下面的代码但没有工作
[Parameter]
public ViewModel viewModel { get; set; }
我写了一篇关于 Blazor 中父子通信的博客post。
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);
}
}
此时,Parent 和 Child 都有一个 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 示例项目的示例,我在用户登录后读取参数:
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
如果你觉得无聊,这里还有一个视频:
也许这会给你一些想法。
如何在 Blazor 中将 ViewModel 从子组件传递到父组件,反之亦然
我正在使用 MVVM 模式构建 Blazor 应用程序。
尝试了下面的代码但没有工作
[Parameter]
public ViewModel viewModel { get; set; }
我写了一篇关于 Blazor 中父子通信的博客post。
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);
}
}
此时,Parent 和 Child 都有一个 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 示例项目的示例,我在用户登录后读取参数:
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
如果你觉得无聊,这里还有一个视频:
也许这会给你一些想法。