Добавление класса компонента с параметром type как свойство в Blazor

Для обычного компонента вы просто объявляете компонент как частное свойство и добавляете имя в качестве параметра @type в определении компонента.

Однако, когда я добавляю компонент с параметром типа и настраиваю его, как показано ниже, код компилируется и запускается, но свойство никогда не заполняется - оно всегда равно null. См. Метод "WantToDoAnUpdate" в последнем блоке кода. Я принудительно обновляю компонент, потому что он использует разбиение на страницы и не обновляется с помощью обычных механизмов Blazor.

CardList.razor

@inherits ComponentComponentBase

@typeparam TItem

........................
create a table of values with pagination
..................

CardList.razor.cs

public partial class CardList<TItem> : ComponentComponentBase
{
  ......
  [Parameter]
  public IReadOnlyList<TItem> Items { get; set; }
  ......
  public void UpdateList()
  {
    ........
  }
}

DeliveryList.razor

@inherits PageComponentBase

<CardList@key="this._MyComponent" TItem="dbDelivery" ....>
</CardList>

DeliveryList.razor.cs

public partial class DeliveryList<TItem> : PageComponentBase
{
  ......
  private CardList<IReadOnlyList<dbDelivery>> _CardList { get; set; }
  ......

  public void WantToDoAnUpdate()
  {
  ....
    --ALWAYS NULL--
    if (this._CardList != null) this._CardList.UpdateList();
  }
}

Я предполагаю, что неправильно объявляю _CardList.


Отлично, спасибо за ответ. Да, я настраивал список, я просто не включил это в код. Cardlist использует предоставленный список для создания страничного списка (страница x из 25 значений), в котором и возникают проблемы. Поскольку отображаемый список представляет собой новый список, полученный в процессе разбиения на страницы из Items, обновление пользовательского интерфейса не происходит, когда Items обновлено. Вызов UpdateList из родительского элемента перенаправляет страничный список и должен запускать обновление производного списка и обновление пользовательского интерфейса.

Однако, поскольку я не мог заставить его работать, я начал копаться в основном коде Blazor на Github, чтобы увидеть, как это делают разработчики Blazor. Теперь я решил проблему другим способом, используя обработчики событий в службе логического уровня, которая содержит список, без необходимости выполнять вызовы из родительского элемента в дочерний, чтобы вызвать обновление. Я также использовал обработчики событий, запускаемые из набора в свойстве, в других случаях, таких как пользовательские элементы управления вводом / отображением.

В любом случае, еще раз спасибо, что нашли время ответить.

1 ответ

Надеюсь, это даст вам то, что вам нужно. Я вижу две вещи, которые, как мне кажется, работают против вас.

Во-первых, в частичном классе Cardlist у вас есть список, украшенный[Parameter]атрибут, но вы никогда не устанавливаете параметр из вызывающего кода. Вам нужно будет установить ОБЕИХTItem и Itemsпараметры, чтобы это работало правильно, поэтому список карточек знает, какой тип содержит список, и где найти список. Помните, что в C# списки являются ссылочным типом, поэтомуItemsвы устанавливаете фактически просто ссылку на любой список, который вы предоставляете, а не сам список в новой форме или новый список в целом. Итак, ваш DeliveryList должен иметь что-то вроде свойства списка, показанного ниже:

public partial class DeliveryList : PageComponentBase
{
  ......
  private <IReadOnlyList<dbDelivery>> CardListContents { get; set; }
  ......
}  

Затем в DeliveryList.razor вы передадите ссылку на список компоненту Cardlist следующим образом:

<CardList @key="this._MyComponent" TItem="dbDelivery" Items="@CardListContents" ....>
</CardList>

Теперь компонент Cardlist становится инструментом визуализации для внешнего списка универсального типа.

Во-вторых, есть некоторая двусмысленность в том, чтоUpdateListпредполагается, но я предполагаю, что вы подключаете кнопку, которая будет вызывать обновление списка при нажатии. Для этого вы можете использовать обратный вызов события в Cardlist.

Ваш Cardlist.razor теперь становится:

@inherits ComponentComponentBase

@typeparam TItem

........................
create a table of values with pagination
..................
<button @onclick="OnUpdateButtonClickedCallBack">Update List</button>

И ваш Cardlist.razor.cs станет:

public partial class CardList<TItem> : ComponentComponentBase
{
  ......
  [Parameter]
  public IReadOnlyList<TItem> Items { get; set; }
  ......
  [Parameter]
  public EventCallBack OnUpdateButtonClickedCallBack { get; set;}
}

Теперь вы настроены так, чтобы указывать на внешний метод, который будет выполняться при каждом нажатии кнопки "Обновить список".

Затем вам нужно подключить метод в своем DeliveryList.razor.cs, и мы сможем использовать ваш WantToUpdateList метод:

public partial class DeliveryList : PageComponentBase
{
  ......
  private <IReadOnlyList<dbDelivery>> CardListContents { get; set; }

  private WantToUpdateList()
  {
      //Since the list is read only you need to generate a new one
      //or call a method from elsewhere that returns a new one,
      //change the method below to suit your needs
      CardListContents = new IReadOnlylist<dbDelivery>();
  }
  ......
}  

Теперь вы можете указать на этот метод с помощью EventCallback, который вы настроили при объявлении Cardlist. Обратите внимание, что конфигурация становится довольно длинной, поэтому я разбил ее на несколько строк:

<CardList @key="this._MyComponent" 
          OnUpdateButtonClickedCallBack="@WantToUpdateList" //Sets the callback function
          TItem="dbDelivery" //Sets the type
          Items="@CardListContents" ....> //Points to the list
</CardList>

Теперь вы можете использовать <Cardlist>компонент с любым списком только для чтения, указав тип, список и функцию обратного вызова, с которой будет работать. Cardlist становится независимым инструментом визуализации, и все состояния, логика и функции для списка находятся в одном месте внутри вызывающего компонента, что делает<CardList>действительно универсальный и портативный. В этом примере любые обновления в списке должны быть получены движком Blazor и инициировать повторный рендеринг, но если нет, вы можете добавить вызов кStateHasChanged(); в качестве последней строки вашего метода обновления в вызывающем коде, и вы должны работать.

Однако обратите внимание, что это решение еще не завершено, так как вам, вероятно, придется добавить несколько RenderFragment логика в Cardlist чтобы указать, как вы хотите визуализировать свою таблицу.

Документация.NET Core отлично справляется с этой задачей.Похоже, вы уже видели это, поскольку стиль кода выглядит одинаково, и не включили его здесь для ясности.

Надеюсь это поможет!

Другие вопросы по тегам