Я хотел бы добавить несколько вариантов использования для ValueChanged
и ValueExpression
,
Прежде всего, как сказал enet, эти свойства больше похожи на троицу свойств, в которых у вас есть Foo
, FooChanged
и FooExpression
и используется в двухсторонней привязке данных, например, @bind-Foo="SomeProperty"
.
Чтобы создать пользовательский компонент со свойством, которое можно использовать с @bind-
, необходимо укажите эти 3 свойства (только при условии, что Foo
и FooChanged
также работают) как [Parameter]
и вызовите FooChanged
, когда свойство в вашем пользовательском компоненте изменится.
например, с enet
[Parameter]
public TValue Foo
{
get => text
set
{
if (text != value) {
text = value;
if (FooChanged.HasDelegate)
{
FooChanged.InvokeAsync(value);
}
}
}
}
[Parameter]
public EventCallback<TValue> FooChanged { get; set; }
[Parameter]
public Expression<Func<TValue>> FooExpression { get; set; }
Добавление @bind-Foo
будет аналогично передаче Value
и ValueChanged
, с той лишь разницей, что @bind-
будет устанавливать только свойство, но если вы добавите свой собственный ValueChanged
, вы можете делайте все, что хотите (проверка, изменение значения для установки и т. д. c).
сценарии использования
1 - создание компонента, который переносит другой компонент с помощью @bind-
Если у вас есть компонент, который уже имеет @bind-Foo
, и вы хотите создать компонент поверх это и все еще передать в качестве параметра @bind-Foo
, вы можете иметь только одно свойство и передать @bind-Foo
, вам нужно передать свойства Foo
, FooChanged
и / или FooExpression
.
например
CustomInputWrapper.razor
<div>
<p>My custom input wrapper</p>
@* If you pass @bind-Value it won't work*@
@* You need to pass the properties that are used in the bind*@
<InputText Text="@Value" TextChanged="@ValueChanged" TextExpression="@ValueExpression" />
</div>
@code {
[Parameter]
public virtual string Value { get; set; }
[Parameter]
public EventCallback<string > ValueChanged { get; set; }
[Parameter]
public Expression<Func<string >> ValueExpression { get; set; }
}
Такая ситуация с обертыванием другого компонента часто случается, если вы создаете много пользовательских компонентов или не хотите напрямую использовать какой-либо сторонний компонент.
Пример моего проекта: в моем проекте я использую MatBlazor и Telerik, но не все компоненты в обеих библиотеках полностью стабильны, поэтому я создал оболочку для всех компонентов и однажды, когда одна из этих библиотек полностью стабильна, я буду использовать только одну библиотеку. Это позволяет мне иметь свои собственные компоненты, и если я хочу изменить один, я изменяю только одну вещь в своем пользовательском компоненте и изменяю все приложение.
2 - Добавление значения по умолчанию
Если вы хотите иметь значение по умолчанию в пользовательском компоненте , вы можете просто передать значение по умолчанию свойству.
[Parameter]
public virtual DateTime Value { get; set; } = new DateTime(/* some default value*/);
Но это будет большой проблемой, если вы используете это компонент внутри формы.
Почему ? Потому что вы будете изменять только значение внутри вашего компонента, но если свойство будет передано в @bind-Value
, оно не будет изменено.
Чтобы добавить это значение по умолчанию и заставить его работать в двустороннем связывании данных Вам нужно позвонить ValueChanged
и передать значение по умолчанию. Это заставит ваш компонент иметь значение по умолчанию, а также изменит любое свойство в @bind-Value
на значение по умолчанию.
например
// Lifecycle after all parameters are set
protected override void OnParametersSet()
{
// Check if the ValueChanged is set
if (ValueChanged.HasDelegate)
{
ValueChanged.InvokeAsync(DateTime.Now);
}
}
3 - используйте тот случай, когда вам действительно нужно FooExpression
... эту часть я пока не знаю, но я действительно ее ищу. Как только я найду его, обновлю здесь.
Вариант использования этих свойств будет использоваться больше, если вы создаете пользовательские компоненты и должны работать со свойством binded или изменить способ работы привязки.
Если вы используете только уже изготовленные компоненты, то в редких случаях вам придется его использовать.