i have component WHERE T can be int or int?
with params like
@typeparam T
@inject DictService _dhttp;
<MudAutocomplete T="string" @bind-Value="ValueString" Label="@Label" For="()=>ValueString" SearchFunc="@SearchFunc"
ResetValueOnEmptyText="true" CoerceValue="true"
OpenIcon="@Icons.Material.Filled.Search" AdornmentColor="Color.Primary"
@attributes=AllOtherAttributes />
[Parameter]
public Expression<Func<T>>? For { get; set; }
[Parameter]
public string? Label { get; set; }
private T _value = default!;
[Parameter]
public T Value
{
get => _value;
set
{
if (!Equals(value, _value))
{
_value = value;
if (ValueChanged.HasDelegate) ValueChanged.InvokeAsync(_value);
}
}
}
[Parameter]
public EventCallback<T?> ValueChanged { get; set; }
private string? _valueString ;
public string? ValueString
{
get{
return _valueString!;
}
set
{
if(!Equals(value, _valueString))
{
_valueString = value;
int? valueInt = _dict!.Values.Where(... some logic to get in val or not)
if (valueInt is null)
{
ValueString = null;
and now this should work for both cases?!? set 0 if int
and null if int?
??
this.Value = (T)(object)default!;
but instead of i have to do
if (typeof(T) == typeof(int))
this.Value = (T)(object)0;
else
this.Value = (T)(object)default!;
}
else this.Value = (T)(object)valueInt;
if (ValueChanged.HasDelegate) ValueChanged.InvokeAsync(_value);
}
}
}
if i do not do this way then in debug i see that if T is int
then (T)(object)default!
like crashes? it should set it to 0 !?
it throws no error. it not go to next line , it just returns to app without changing value of this.Value
witch is int in this case. value stays as it was from previous run
is it a .net blazor bug? or am missing something here ?
Here is some githup repo that shows this issue
https://github.com/d00lar/TconverterFails
in this line
<MudSelectItem Value="TConverter.ChangeType<T>(item.Key)">@item.Value</MudSelectItem>
if i do casting based on this int/int? switch then it will wotk fine otherwise throw as in topic
You are overcomplicating your cast.
Just use default
which will set type int
to 0
, and type int?
to null
.
Index.razor:
@page "/"
<MyComponent T="int" />
<MyComponent T="int?" />
Component:
@using System.ComponentModel
@typeparam T
<div>
<input type="text" @bind-value="@ValueString" />
<span>@(Value == null ? "null" : Value)</span>
</div>
@code {
T Value { get; set; }
string _valueString = "";
string? ValueString
{
get
{
return _valueString!;
}
set
{
_valueString = value;
if (string.IsNullOrEmpty(value))
{
this.Value = default;
}
else this.Value = TConverter.ChangeType<T>(value); ;
Console.WriteLine(_valueString);
}
}
public static class TConverter
{
public static T ChangeType<T>(object value)
{
return (T)ChangeType(typeof(T), value);
}
public static object ChangeType(Type t, object value)
{
TypeConverter tc = TypeDescriptor.GetConverter(t);
return tc.ConvertFrom(value);
}
public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
{
TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
}
}
}
TConverter
source: https://stackoverflow.com/a/1833128/2286743
I can see in your approach that your understanding of how to implement components needs to be expanded. I suggest you go through the documentation provided by Microsoft, and improve your understanding.
As a side note, using a dictionary is not the right way of doing it, since the Key
in a Dictionary cannot be null. This can however be overcome as mentioned here: Why doesn't Dictionary<TKey, TValue> support null key?
@page "/"
@using MyApplication.Shared
<PageTitle>Index</PageTitle>
<IntStrDictMudSelectComponent @bind-Value="@intvar" Data="@Data" For="@(()=>intvar)" />
@code {
private int intvar = 1;
Dictionary<int, string> Data = new Dictionary<int, string>() {
{ 1, "Value 1" },
{ 2, "Value 2" },
{ 3, "Value 3" },
{ 4, "Value 4" },
{ 5, "Value 5" },
{ 6, "Value 6" }
};
}
@using System.Linq.Expressions
@typeparam T
<MudSelect T="T" @bind-Value="@Value" For="@For">
@foreach (var item in Data)
{
<MudSelectItem Value="item.Key">@item.Value</MudSelectItem>
}
</MudSelect>
@code {
[EditorRequired]
[Parameter]
public Expression<Func<T>>? For { get; set; }
T _value = default!;
[EditorRequired]
[Parameter]
public T Value
{
get => _value;
set
{
if (!Equals(value, _value))
{
_value = value;
if (ValueChanged.HasDelegate)
ValueChanged.InvokeAsync(_value);
}
}
}
[EditorRequired]
[Parameter]
public EventCallback<T> ValueChanged { get; set; }
[EditorRequired]
[Parameter]
public Dictionary<T, string> Data { get; set; }
}