mirror of
https://github.com/radzenhq/radzen-blazor.git
synced 2026-02-04 05:35:44 +00:00
Various warnings resolved and TreatWarningsAsErrors enabled (#2409)
This commit is contained in:
73
Directory.Build.props
Normal file
73
Directory.Build.props
Normal file
@@ -0,0 +1,73 @@
|
||||
<Project>
|
||||
<!--
|
||||
Common build properties for all projects in the Radzen.Blazor solution.
|
||||
|
||||
To use this file:
|
||||
1. Rename to Directory.Build.props (remove .sample extension)
|
||||
2. Adjust settings based on your needs
|
||||
3. Review the analyzer settings in .editorconfig
|
||||
|
||||
This file will be automatically imported by all projects in subdirectories.
|
||||
-->
|
||||
|
||||
<PropertyGroup Label="Language Configuration">
|
||||
<!-- Use latest C# language features -->
|
||||
<LangVersion>latest</LangVersion>
|
||||
|
||||
<!-- Do NOT enable implicit usings - explicit imports preferred for library code -->
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>CA2007</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Code Analysis Configuration">
|
||||
<!-- Enable .NET code analyzers -->
|
||||
<AnalysisLevel>latest</AnalysisLevel>
|
||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||
|
||||
<!-- Run analyzers during build and in IDE -->
|
||||
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
|
||||
<RunAnalyzersDuringLiveAnalysis>true</RunAnalyzersDuringLiveAnalysis>
|
||||
|
||||
<!-- Don't enforce code style in build (yet) - just show warnings -->
|
||||
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
|
||||
|
||||
<!-- Don't treat warnings as errors (yet) - too many to fix immediately -->
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
|
||||
<!-- Report all analyzer diagnostics -->
|
||||
<AnalysisMode>All</AnalysisMode>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Build Quality">
|
||||
<!-- Enable deterministic builds for reproducibility -->
|
||||
<Deterministic>true</Deterministic>
|
||||
|
||||
<!-- Enable deterministic builds in CI/CD -->
|
||||
<ContinuousIntegrationBuild Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
|
||||
|
||||
<!-- Embed source files for better debugging -->
|
||||
<EmbedAllSources>true</EmbedAllSources>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Demos and Tests Project Configuration" Condition="$(MSBuildProjectName.Contains('Demos')) OR $(MSBuildProjectName.Contains('Tests'))">
|
||||
<!-- Demo projects and Tests should not be packable -->
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<!-- DISABLE ALL ANALYZERS FOR DEMO PROJECTS AND TESTS -->
|
||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
||||
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
|
||||
<RunAnalyzersDuringLiveAnalysis>false</RunAnalyzersDuringLiveAnalysis>
|
||||
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Performance">
|
||||
<!-- Optimize startup time -->
|
||||
<TieredCompilation>true</TieredCompilation>
|
||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Radzen.Blazor.Tests
|
||||
public Guid Id { get; set; }
|
||||
public TimeOnly StartTime { get; set; }
|
||||
public DateOnly BirthDate { get; set; }
|
||||
public List<int> Scores { get; set; }
|
||||
public IEnumerable<int> Scores { get; set; }
|
||||
public List<string> Tags { get; set; }
|
||||
public List<TestEntity> Children { get; set; }
|
||||
public Address Address { get; set; }
|
||||
|
||||
@@ -605,7 +605,7 @@ namespace Radzen.Blazor.Tests
|
||||
Assert.True(grid.AllowFieldsPicking);
|
||||
}
|
||||
|
||||
private static IRenderedComponent<RadzenPivotDataGrid<SalesData>> RenderPivotDataGrid(TestContext ctx, Action<ComponentParameterCollectionBuilder<RadzenPivotDataGrid<SalesData>>>? configure = null)
|
||||
private static IRenderedComponent<RadzenPivotDataGrid<SalesData>> RenderPivotDataGrid(TestContext ctx, Action<ComponentParameterCollectionBuilder<RadzenPivotDataGrid<SalesData>>> configure = null)
|
||||
{
|
||||
return ctx.RenderComponent<RadzenPivotDataGrid<SalesData>>(parameters =>
|
||||
{
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net10.0</TargetFramework>
|
||||
|
||||
<Nullable>disable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -6,6 +6,48 @@ root = true
|
||||
|
||||
#### Core EditorConfig Options ####
|
||||
|
||||
dotnet_diagnostic.CA1002.severity = none
|
||||
dotnet_diagnostic.CA1003.severity = none
|
||||
dotnet_diagnostic.CA1024.severity = none
|
||||
dotnet_diagnostic.CA1030.severity = none
|
||||
dotnet_diagnostic.CA1031.severity = none
|
||||
dotnet_diagnostic.CA1033.severity = none
|
||||
dotnet_diagnostic.CA1044.severity = none
|
||||
dotnet_diagnostic.CA1050.severity = none
|
||||
dotnet_diagnostic.CA1051.severity = none
|
||||
dotnet_diagnostic.CA1052.severity = none
|
||||
dotnet_diagnostic.CA1054.severity = none
|
||||
dotnet_diagnostic.CA1055.severity = none
|
||||
dotnet_diagnostic.CA1056.severity = none
|
||||
dotnet_diagnostic.CA1063.severity = none
|
||||
dotnet_diagnostic.CA1068.severity = none
|
||||
dotnet_diagnostic.CA1308.severity = none
|
||||
dotnet_diagnostic.CA1708.severity = none
|
||||
dotnet_diagnostic.CA1711.severity = none
|
||||
dotnet_diagnostic.CA1716.severity = none
|
||||
dotnet_diagnostic.CA1720.severity = none
|
||||
dotnet_diagnostic.CA1721.severity = none
|
||||
dotnet_diagnostic.CA1724.severity = none
|
||||
dotnet_diagnostic.CA1725.severity = none
|
||||
dotnet_diagnostic.CA1802.severity = none
|
||||
dotnet_diagnostic.CA1814.severity = none
|
||||
dotnet_diagnostic.CA1815.severity = none
|
||||
dotnet_diagnostic.CA1816.severity = none
|
||||
dotnet_diagnostic.CA1819.severity = none
|
||||
dotnet_diagnostic.CA1822.severity = none
|
||||
dotnet_diagnostic.CA1827.severity = none
|
||||
dotnet_diagnostic.CA1834.severity = none
|
||||
dotnet_diagnostic.CA1845.severity = none
|
||||
dotnet_diagnostic.CA1849.severity = none
|
||||
dotnet_diagnostic.CA1851.severity = none
|
||||
dotnet_diagnostic.CA1859.severity = none
|
||||
dotnet_diagnostic.CA1863.severity = none
|
||||
dotnet_diagnostic.CA1869.severity = none
|
||||
dotnet_diagnostic.CA2007.severity = none
|
||||
dotnet_diagnostic.CA2012.severity = none
|
||||
dotnet_diagnostic.CA2211.severity = none
|
||||
dotnet_diagnostic.CA2227.severity = none
|
||||
|
||||
# Indentation and spacing
|
||||
indent_size = 4
|
||||
indent_style = space
|
||||
@@ -21,13 +21,16 @@ public class AIChatService(IServiceProvider serviceProvider, IOptions<AIChatServ
|
||||
private readonly Dictionary<string, ConversationSession> sessions = new();
|
||||
private readonly object sessionsLock = new();
|
||||
|
||||
// Add this static field to cache the JsonSerializerOptions instance
|
||||
private static readonly JsonSerializerOptions CachedJsonSerializerOptions = new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull };
|
||||
|
||||
/// <summary>
|
||||
/// Gets the configuration options for the chat streaming service.
|
||||
/// </summary>
|
||||
public AIChatServiceOptions Options => options.Value;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async IAsyncEnumerable<string> GetCompletionsAsync(string userInput, string sessionId = null, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default, string model = null, string systemPrompt = null, double? temperature = null, int? maxTokens = null, string endpoint = null, string proxy = null, string apiKey = null, string apiKeyHeader = null)
|
||||
public async IAsyncEnumerable<string> GetCompletionsAsync(string userInput, string? sessionId = null, [System.Runtime.CompilerServices.EnumeratorCancellation] CancellationToken cancellationToken = default, string? model = null, string? systemPrompt = null, double? temperature = null, int? maxTokens = null, string? endpoint = null, string? proxy = null, string? apiKey = null, string? apiKeyHeader = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(userInput))
|
||||
{
|
||||
@@ -57,13 +60,18 @@ public class AIChatService(IServiceProvider serviceProvider, IOptions<AIChatServ
|
||||
stream = true
|
||||
};
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, url)
|
||||
using var request = new HttpRequestMessage(HttpMethod.Post, url)
|
||||
{
|
||||
Content = new StringContent(JsonSerializer.Serialize(payload, new JsonSerializerOptions { DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }), Encoding.UTF8, "application/json")
|
||||
Content = new StringContent(JsonSerializer.Serialize(payload, CachedJsonSerializerOptions), Encoding.UTF8, "application/json")
|
||||
};
|
||||
|
||||
if (!string.IsNullOrEmpty(effectiveApiKey))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(effectiveApiKeyHeader))
|
||||
{
|
||||
throw new InvalidOperationException("API key header must be specified when an API key is provided.");
|
||||
}
|
||||
|
||||
if (string.Equals(effectiveApiKeyHeader, "Authorization", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", effectiveApiKey);
|
||||
@@ -75,22 +83,22 @@ public class AIChatService(IServiceProvider serviceProvider, IOptions<AIChatServ
|
||||
}
|
||||
|
||||
var httpClient = serviceProvider.GetRequiredService<HttpClient>();
|
||||
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken);
|
||||
var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (!response.IsSuccessStatusCode)
|
||||
{
|
||||
throw new Exception($"Chat stream failed: {await response.Content.ReadAsStringAsync(cancellationToken)}");
|
||||
throw new HttpRequestException($"Chat stream failed: {await response.Content.ReadAsStringAsync(cancellationToken).ConfigureAwait(false)}");
|
||||
}
|
||||
|
||||
using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
|
||||
using var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
|
||||
using var reader = new StreamReader(stream);
|
||||
|
||||
var assistantResponse = new StringBuilder();
|
||||
|
||||
string line;
|
||||
string? line;
|
||||
while ((line = await reader.ReadLineAsync()) is not null && !cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(line) || !line.StartsWith("data:"))
|
||||
if (string.IsNullOrWhiteSpace(line) || !line.StartsWith("data:", StringComparison.Ordinal))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -118,7 +126,7 @@ public class AIChatService(IServiceProvider serviceProvider, IOptions<AIChatServ
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ConversationSession GetOrCreateSession(string sessionId = null)
|
||||
public ConversationSession GetOrCreateSession(string? sessionId = null)
|
||||
{
|
||||
lock (sessionsLock)
|
||||
{
|
||||
@@ -182,9 +190,14 @@ public class AIChatService(IServiceProvider serviceProvider, IOptions<AIChatServ
|
||||
|
||||
private static string ParseStreamingResponse(string json)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(json))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var doc = JsonDocument.Parse(json);
|
||||
using var doc = JsonDocument.Parse(json);
|
||||
var root = doc.RootElement;
|
||||
|
||||
if (!root.TryGetProperty("choices", out var choices) || choices.GetArrayLength() == 0)
|
||||
@@ -206,7 +219,11 @@ public class AIChatService(IServiceProvider serviceProvider, IOptions<AIChatServ
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
catch
|
||||
catch (JsonException)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
catch (FormatException)
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
@@ -16,15 +16,8 @@ public static class AIChatServiceExtensions
|
||||
/// <returns>The updated service collection.</returns>
|
||||
public static IServiceCollection AddAIChatService(this IServiceCollection services, Action<AIChatServiceOptions> configureOptions)
|
||||
{
|
||||
if (services == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(services));
|
||||
}
|
||||
|
||||
if (configureOptions == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(configureOptions));
|
||||
}
|
||||
ArgumentNullException.ThrowIfNull(services);
|
||||
ArgumentNullException.ThrowIfNull(configureOptions);
|
||||
|
||||
services.Configure(configureOptions);
|
||||
services.AddScoped<IAIChatService, AIChatService>();
|
||||
|
||||
@@ -13,7 +13,7 @@ public class AIChatServiceOptions
|
||||
/// <summary>
|
||||
/// Gets or sets the proxy URL for the AI service, if any. If set, this will override the Endpoint.
|
||||
/// </summary>
|
||||
public string Proxy { get; set; } = null;
|
||||
public string? Proxy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the API key for authentication with the AI service.
|
||||
@@ -28,7 +28,7 @@ public class AIChatServiceOptions
|
||||
/// <summary>
|
||||
/// Gets or sets the model name to use for executing chat completions (e.g., 'gpt-3.5-turbo').
|
||||
/// </summary>
|
||||
public string Model { get; set; }
|
||||
public string? Model { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the system prompt for the AI assistant.
|
||||
|
||||
@@ -22,19 +22,19 @@ namespace Radzen.Blazor
|
||||
/// Gets or sets the text of the appointment.
|
||||
/// </summary>
|
||||
/// <value>The text.</value>
|
||||
public string Text { get; set; }
|
||||
public string? Text { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the data associated with the appointment
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
public object Data { get; set; }
|
||||
public object? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified object is equal to this instance. Used to check if two appointments are equal.
|
||||
/// </summary>
|
||||
/// <param name="obj">The object to compare with this instance.</param>
|
||||
/// <returns><c>true</c> if the specified is equal to this instance; otherwise, <c>false</c>.</returns>
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is AppointmentData data &&
|
||||
Start == data.Start &&
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The stroke.</value>
|
||||
[Parameter]
|
||||
public string Stroke { get; set; }
|
||||
public string? Stroke { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the pixel width of axis.
|
||||
/// </summary>
|
||||
@@ -26,21 +26,21 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
public RenderFragment? ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format string used to display the axis values.
|
||||
/// </summary>
|
||||
/// <value>The format string.</value>
|
||||
[Parameter]
|
||||
public string FormatString { get; set; }
|
||||
public string? FormatString { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a formatter function that formats the axis values.
|
||||
/// </summary>
|
||||
/// <value>The formatter.</value>
|
||||
[Parameter]
|
||||
public Func<object, string> Formatter { get; set; }
|
||||
public Func<object, string>? Formatter { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the line used to display the axis.
|
||||
@@ -80,20 +80,20 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The minimum.</value>
|
||||
[Parameter]
|
||||
public object Min { get; set; }
|
||||
public object? Min { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the maximum value of the axis.
|
||||
/// </summary>
|
||||
/// <value>The maximum.</value>
|
||||
[Parameter]
|
||||
public object Max { get; set; }
|
||||
public object? Max { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the step of the axis.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public object Step { get; set; }
|
||||
public object? Step { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="AxisBase"/> is visible.
|
||||
@@ -139,7 +139,7 @@ namespace Radzen.Blazor
|
||||
}
|
||||
else
|
||||
{
|
||||
return scale.FormatTick(FormatString, value);
|
||||
return scale.FormatTick(FormatString ?? string.Empty, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,17 @@ namespace Radzen.Blazor
|
||||
/// Cache for the value returned by <see cref="Category"/> when that value is only dependent on
|
||||
/// <see cref="CategoryProperty"/>.
|
||||
/// </summary>
|
||||
Func<TItem, double> categoryPropertyCache;
|
||||
Func<TItem, double>? categoryPropertyCache;
|
||||
|
||||
/// <summary>
|
||||
/// Returns the parent <see cref="RadzenChart"/> instance or throws an <see cref="InvalidOperationException"/> if not present.
|
||||
/// </summary>
|
||||
/// <returns>The parent <see cref="RadzenChart"/>.</returns>
|
||||
/// <exception cref="InvalidOperationException">Thrown when the parent chart is not set.</exception>
|
||||
protected RadzenChart RequireChart()
|
||||
{
|
||||
return Chart ?? throw new InvalidOperationException($"{GetType().Name} requires a parent RadzenChart.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a getter function that returns a value from the specified category scale for the specified data item.
|
||||
@@ -34,13 +44,13 @@ namespace Radzen.Blazor
|
||||
|
||||
if (IsNumeric(CategoryProperty))
|
||||
{
|
||||
categoryPropertyCache = PropertyAccess.Getter<TItem, double>(CategoryProperty);
|
||||
categoryPropertyCache = PropertyAccess.Getter<TItem, double>(CategoryProperty!);
|
||||
return categoryPropertyCache;
|
||||
}
|
||||
|
||||
if (IsDate(CategoryProperty))
|
||||
{
|
||||
var category = PropertyAccess.Getter<TItem, DateTime>(CategoryProperty);
|
||||
var category = PropertyAccess.Getter<TItem, DateTime>(CategoryProperty!);
|
||||
categoryPropertyCache = (item) => category(item).Ticks;
|
||||
return categoryPropertyCache;
|
||||
}
|
||||
@@ -49,7 +59,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
Func<TItem, object> category = String.IsNullOrEmpty(CategoryProperty) ? (item) => string.Empty : PropertyAccess.Getter<TItem, object>(CategoryProperty);
|
||||
|
||||
return (item) => ordinal.Data.IndexOf(category(item));
|
||||
return (item) => ordinal.Data?.IndexOf(category(item)) ?? -1;
|
||||
}
|
||||
|
||||
return (item) => Items.IndexOf(item);
|
||||
@@ -60,6 +70,8 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
protected Func<TItem, double> ComposeCategory(ScaleBase scale)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(scale);
|
||||
|
||||
return scale.Compose(Category(scale));
|
||||
}
|
||||
|
||||
@@ -68,6 +80,8 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
protected Func<TItem, double> ComposeValue(ScaleBase scale)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(scale);
|
||||
|
||||
return scale.Compose(Value);
|
||||
}
|
||||
|
||||
@@ -77,7 +91,7 @@ namespace Radzen.Blazor
|
||||
/// <param name="propertyName">Name of the property.</param>
|
||||
/// <returns><c>true</c> if the specified property name is date; otherwise, <c>false</c>.</returns>
|
||||
/// <exception cref="ArgumentException">Property {propertyName} does not exist</exception>
|
||||
protected bool IsDate(string propertyName)
|
||||
protected bool IsDate(string? propertyName)
|
||||
{
|
||||
if (String.IsNullOrEmpty(propertyName))
|
||||
{
|
||||
@@ -106,7 +120,7 @@ namespace Radzen.Blazor
|
||||
/// <param name="propertyName">Name of the property.</param>
|
||||
/// <returns><c>true</c> if the specified property name is numeric; otherwise, <c>false</c>.</returns>
|
||||
/// <exception cref="ArgumentException">Property {propertyName} does not exist</exception>
|
||||
protected bool IsNumeric(string propertyName)
|
||||
protected bool IsNumeric(string? propertyName)
|
||||
{
|
||||
if (String.IsNullOrEmpty(propertyName))
|
||||
{
|
||||
@@ -125,21 +139,21 @@ namespace Radzen.Blazor
|
||||
|
||||
/// <inheritdoc />
|
||||
[Parameter]
|
||||
public string Title { get; set; }
|
||||
public string Title { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent { get; set; }
|
||||
public RenderFragment? ChildContent { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tooltip template.
|
||||
/// </summary>
|
||||
/// <value>The tooltip template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment<TItem> TooltipTemplate { get; set; }
|
||||
public RenderFragment<TItem>? TooltipTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of overlays.
|
||||
@@ -157,7 +171,7 @@ namespace Radzen.Blazor
|
||||
/// The name of the property of <typeparamref name="TItem" /> that provides the X axis (a.k.a. category axis) values.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string CategoryProperty { get; set; }
|
||||
public string? CategoryProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="CartesianSeries{TItem}"/> is visible.
|
||||
@@ -194,7 +208,7 @@ namespace Radzen.Blazor
|
||||
/// The name of the property of <typeparamref name="TItem" /> that provides the Y axis (a.k.a. value axis) values.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string ValueProperty { get; set; }
|
||||
public string? ValueProperty { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
[Parameter]
|
||||
@@ -223,7 +237,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
[Parameter]
|
||||
public IEnumerable<TItem> Data { get; set; }
|
||||
public IEnumerable<TItem>? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Stores <see cref="Data" /> as an IList of <typeparamref name="TItem"/>.
|
||||
@@ -272,6 +286,8 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
public virtual ScaleBase TransformCategoryScale(ScaleBase scale)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(scale);
|
||||
|
||||
if (Items == null)
|
||||
{
|
||||
return scale;
|
||||
@@ -298,7 +314,7 @@ namespace Radzen.Blazor
|
||||
|
||||
var data = GetCategories();
|
||||
|
||||
if (scale is OrdinalScale ordinal)
|
||||
if (scale is OrdinalScale ordinal && ordinal.Data != null)
|
||||
{
|
||||
foreach (var item in ordinal.Data)
|
||||
{
|
||||
@@ -328,6 +344,8 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
public virtual ScaleBase TransformValueScale(ScaleBase scale)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(scale);
|
||||
|
||||
if (Items != null)
|
||||
{
|
||||
if (Items.Any())
|
||||
@@ -398,29 +416,32 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (Data != null)
|
||||
{
|
||||
if (Data is IList<TItem>)
|
||||
if (Data is IList<TItem> list)
|
||||
{
|
||||
Items = Data as IList<TItem>;
|
||||
Items = list;
|
||||
}
|
||||
else
|
||||
{
|
||||
Items = Data.ToList();
|
||||
}
|
||||
|
||||
if (IsDate(CategoryProperty) || IsNumeric(CategoryProperty))
|
||||
if (!string.IsNullOrEmpty(CategoryProperty) && (IsDate(CategoryProperty) || IsNumeric(CategoryProperty)))
|
||||
{
|
||||
Items = Items.AsQueryable().OrderBy(CategoryProperty).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
await Chart.Refresh(false);
|
||||
if (Chart != null)
|
||||
{
|
||||
await Chart.Refresh(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Initialize()
|
||||
{
|
||||
Chart.AddSeries(this);
|
||||
Chart?.AddSeries(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -443,6 +464,9 @@ namespace Radzen.Blazor
|
||||
/// <returns><c>true</c> if the polygon contains the point, <c>false</c> otherwise.</returns>
|
||||
protected bool InsidePolygon(Point point, Point[] polygon)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(point);
|
||||
ArgumentNullException.ThrowIfNull(polygon);
|
||||
|
||||
var minX = polygon[0].X;
|
||||
var maxX = polygon[0].X;
|
||||
var minY = polygon[0].Y;
|
||||
@@ -479,18 +503,22 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
public virtual RenderFragment RenderTooltip(object data)
|
||||
{
|
||||
var chart = RequireChart();
|
||||
var item = (TItem)data;
|
||||
|
||||
return builder =>
|
||||
{
|
||||
if (Chart.Tooltip.Shared)
|
||||
if (chart.Tooltip.Shared)
|
||||
{
|
||||
var category = PropertyAccess.GetValue(item, CategoryProperty);
|
||||
builder.OpenComponent<ChartSharedTooltip>(0);
|
||||
builder.AddAttribute(1, nameof(ChartSharedTooltip.Class), TooltipClass(item));
|
||||
builder.AddAttribute(2, nameof(ChartSharedTooltip.Title), TooltipTitle(item));
|
||||
builder.AddAttribute(3, nameof(ChartSharedTooltip.ChildContent), RenderSharedTooltipItems(category));
|
||||
builder.CloseComponent();
|
||||
var category = !string.IsNullOrEmpty(CategoryProperty) ? PropertyAccess.GetValue(item, CategoryProperty) : null;
|
||||
if (category != null)
|
||||
{
|
||||
builder.OpenComponent<ChartSharedTooltip>(0);
|
||||
builder.AddAttribute(1, nameof(ChartSharedTooltip.Class), TooltipClass(item));
|
||||
builder.AddAttribute(2, nameof(ChartSharedTooltip.Title), TooltipTitle(item));
|
||||
builder.AddAttribute(3, nameof(ChartSharedTooltip.ChildContent), RenderSharedTooltipItems(category));
|
||||
builder.CloseComponent();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -508,9 +536,11 @@ namespace Radzen.Blazor
|
||||
|
||||
private RenderFragment RenderSharedTooltipItems(object category)
|
||||
{
|
||||
var chart = RequireChart();
|
||||
|
||||
return builder =>
|
||||
{
|
||||
var visibleSeries = Chart.Series.Where(s => s.Visible).ToList();
|
||||
var visibleSeries = chart.Series.Where(s => s.Visible).ToList();
|
||||
|
||||
foreach (var series in visibleSeries)
|
||||
{
|
||||
@@ -524,7 +554,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
return builder =>
|
||||
{
|
||||
var item = Items.FirstOrDefault(i => object.Equals(PropertyAccess.GetValue(i, CategoryProperty), category));
|
||||
var item = Items.FirstOrDefault(i => !string.IsNullOrEmpty(CategoryProperty) && object.Equals(PropertyAccess.GetValue(i, CategoryProperty), category));
|
||||
|
||||
if (item != null)
|
||||
{
|
||||
@@ -553,7 +583,7 @@ namespace Radzen.Blazor
|
||||
/// <param name="item">The item.</param>
|
||||
protected virtual string TooltipStyle(TItem item)
|
||||
{
|
||||
return Chart.Tooltip.Style;
|
||||
return Chart?.Tooltip?.Style ?? string.Empty;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -562,7 +592,13 @@ namespace Radzen.Blazor
|
||||
/// <param name="item">The item.</param>
|
||||
protected virtual string TooltipClass(TItem item)
|
||||
{
|
||||
return $"rz-series-{Chart.Series.IndexOf(this)}-tooltip";
|
||||
var chart = Chart;
|
||||
if (chart == null)
|
||||
{
|
||||
return "rz-series-tooltip";
|
||||
}
|
||||
|
||||
return $"rz-series-{chart.Series.IndexOf(this)}-tooltip";
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -576,6 +612,8 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
protected virtual RenderFragment RenderLegendItem(bool clickable)
|
||||
{
|
||||
var chart = RequireChart();
|
||||
var index = chart.Series.IndexOf(this);
|
||||
var style = new List<string>();
|
||||
|
||||
if (IsVisible == false)
|
||||
@@ -586,7 +624,7 @@ namespace Radzen.Blazor
|
||||
return builder =>
|
||||
{
|
||||
builder.OpenComponent<LegendItem>(0);
|
||||
builder.AddAttribute(1, nameof(LegendItem.Index), Chart.Series.IndexOf(this));
|
||||
builder.AddAttribute(1, nameof(LegendItem.Index), index);
|
||||
builder.AddAttribute(2, nameof(LegendItem.Color), Color);
|
||||
builder.AddAttribute(3, nameof(LegendItem.MarkerType), MarkerType);
|
||||
builder.AddAttribute(4, nameof(LegendItem.Style), string.Join(";", style));
|
||||
@@ -617,19 +655,35 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
public double GetMedian()
|
||||
{
|
||||
return Data.Select(e => Value(e)).OrderBy(e => e).Skip(Data.Count() / 2).FirstOrDefault();
|
||||
var values = Items.Select(Value).OrderBy(e => e).ToList();
|
||||
if (values.Count == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return values[values.Count / 2];
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMean()
|
||||
{
|
||||
return Data.Select(e => Value(e)).DefaultIfEmpty(double.NaN).Average();
|
||||
return Items.Any() ? Items.Select(Value).Average() : double.NaN;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMode()
|
||||
{
|
||||
return Data.Any() ? Data.GroupBy(e => Value(e)).Select(g => new { Value = g.Key, Count = g.Count() }).OrderByDescending(e => e.Count).FirstOrDefault().Value : double.NaN;
|
||||
if (!Items.Any())
|
||||
{
|
||||
return double.NaN;
|
||||
}
|
||||
|
||||
return Items
|
||||
.GroupBy(item => Value(item))
|
||||
.Select(g => new { Value = g.Key, Count = g.Count() })
|
||||
.OrderByDescending(e => e.Count)
|
||||
.First()
|
||||
.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -639,33 +693,43 @@ namespace Radzen.Blazor
|
||||
{
|
||||
double a = double.NaN, b = double.NaN;
|
||||
|
||||
if (Data.Any())
|
||||
var chart = Chart;
|
||||
if (chart == null)
|
||||
{
|
||||
return (a, b);
|
||||
}
|
||||
|
||||
if (Items.Any())
|
||||
{
|
||||
Func<TItem, double> X;
|
||||
Func<TItem, double> Y;
|
||||
if (Chart.ShouldInvertAxes())
|
||||
if (chart.ShouldInvertAxes())
|
||||
{
|
||||
X = e => Chart.CategoryScale.Scale(Value(e));
|
||||
Y = e => Chart.ValueScale.Scale(Category(Chart.ValueScale)(e));
|
||||
var valueScale = chart.ValueScale;
|
||||
var categoryAccessor = Category(chart.ValueScale);
|
||||
X = e => chart.CategoryScale.Scale(Value(e));
|
||||
Y = e => valueScale.Scale(categoryAccessor(e));
|
||||
}
|
||||
else
|
||||
{
|
||||
X = e => Chart.CategoryScale.Scale(Category(Chart.CategoryScale)(e));
|
||||
Y = e => Chart.ValueScale.Scale(Value(e));
|
||||
var categoryAccessor = Category(chart.CategoryScale);
|
||||
X = e => chart.CategoryScale.Scale(categoryAccessor(e));
|
||||
Y = e => chart.ValueScale.Scale(Value(e));
|
||||
}
|
||||
|
||||
var avgX = Data.Select(e => X(e)).Average();
|
||||
var avgY = Data.Select(e => Y(e)).Average();
|
||||
var sumXY = Data.Sum(e => (X(e) - avgX) * (Y(e) - avgY));
|
||||
if (Chart.ShouldInvertAxes())
|
||||
var data = Items.ToList();
|
||||
var avgX = data.Select(e => X(e)).Average();
|
||||
var avgY = data.Select(e => Y(e)).Average();
|
||||
var sumXY = data.Sum(e => (X(e) - avgX) * (Y(e) - avgY));
|
||||
if (chart.ShouldInvertAxes())
|
||||
{
|
||||
var sumYSq = Data.Sum(e => (Y(e) - avgY) * (Y(e) - avgY));
|
||||
var sumYSq = data.Sum(e => (Y(e) - avgY) * (Y(e) - avgY));
|
||||
b = sumXY / sumYSq;
|
||||
a = avgX - b * avgY;
|
||||
}
|
||||
else
|
||||
{
|
||||
var sumXSq = Data.Sum(e => (X(e) - avgX) * (X(e) - avgX));
|
||||
var sumXSq = data.Sum(e => (X(e) - avgX) * (X(e) - avgX));
|
||||
b = sumXY / sumXSq;
|
||||
a = avgY - b * avgX;
|
||||
}
|
||||
@@ -678,7 +742,9 @@ namespace Radzen.Blazor
|
||||
{
|
||||
IsVisible = !IsVisible;
|
||||
|
||||
if (Chart.LegendClick.HasDelegate)
|
||||
var chart = Chart;
|
||||
|
||||
if (chart?.LegendClick.HasDelegate == true)
|
||||
{
|
||||
var args = new LegendClickEventArgs
|
||||
{
|
||||
@@ -687,18 +753,28 @@ namespace Radzen.Blazor
|
||||
IsVisible = IsVisible,
|
||||
};
|
||||
|
||||
await Chart.LegendClick.InvokeAsync(args);
|
||||
await chart.LegendClick.InvokeAsync(args);
|
||||
|
||||
IsVisible = args.IsVisible;
|
||||
}
|
||||
|
||||
await Chart.Refresh();
|
||||
if (chart != null)
|
||||
{
|
||||
await chart.Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetTitle()
|
||||
{
|
||||
return String.IsNullOrEmpty(Title) ? $"Series {Chart.Series.IndexOf(this) + 1}" : Title;
|
||||
var chart = Chart;
|
||||
if (string.IsNullOrEmpty(Title))
|
||||
{
|
||||
var index = chart?.Series.IndexOf(this) ?? 0;
|
||||
return $"Series {index + 1}";
|
||||
}
|
||||
|
||||
return Title;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -716,8 +792,9 @@ namespace Radzen.Blazor
|
||||
/// <param name="item">The item.</param>
|
||||
protected virtual string TooltipTitle(TItem item)
|
||||
{
|
||||
var category = Category(Chart.CategoryScale);
|
||||
return Chart.CategoryAxis.Format(Chart.CategoryScale, Chart.CategoryScale.Value(category(item)));
|
||||
var chart = RequireChart();
|
||||
var category = Category(chart.CategoryScale);
|
||||
return chart.CategoryAxis.Format(chart.CategoryScale, chart.CategoryScale.Value(category(item)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -727,7 +804,8 @@ namespace Radzen.Blazor
|
||||
/// <returns>System.String.</returns>
|
||||
protected virtual string TooltipValue(TItem item)
|
||||
{
|
||||
return Chart.ValueAxis.Format(Chart.ValueScale, Chart.ValueScale.Value(Value(item)));
|
||||
var chart = RequireChart();
|
||||
return chart.ValueAxis.Format(chart.ValueScale, chart.ValueScale.Value(Value(item)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -736,8 +814,9 @@ namespace Radzen.Blazor
|
||||
/// <param name="item">The item.</param>
|
||||
internal virtual double TooltipX(TItem item)
|
||||
{
|
||||
var category = Category(Chart.CategoryScale);
|
||||
return Chart.CategoryScale.Scale(category(item), true);
|
||||
var chart = RequireChart();
|
||||
var category = Category(chart.CategoryScale);
|
||||
return chart.CategoryScale.Scale(category(item), true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -746,7 +825,8 @@ namespace Radzen.Blazor
|
||||
/// <param name="item">The item.</param>
|
||||
internal virtual double TooltipY(TItem item)
|
||||
{
|
||||
return Chart.ValueScale.Scale(Value(item), true);
|
||||
var chart = RequireChart();
|
||||
return chart.ValueScale.Scale(Value(item), true);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -760,25 +840,26 @@ namespace Radzen.Blazor
|
||||
return new { Item = item, Distance = distance };
|
||||
}).Aggregate((a, b) => a.Distance < b.Distance ? a : b).Item;
|
||||
|
||||
return (retObject,
|
||||
return (retObject!,
|
||||
new Point() { X = TooltipX(retObject), Y = TooltipY(retObject)});
|
||||
}
|
||||
|
||||
return (null, null);
|
||||
return (default!, new Point());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual IEnumerable<ChartDataLabel> GetDataLabels(double offsetX, double offsetY)
|
||||
{
|
||||
var chart = RequireChart();
|
||||
var list = new List<ChartDataLabel>();
|
||||
|
||||
foreach (var d in Data)
|
||||
foreach (var d in Items)
|
||||
{
|
||||
list.Add(new ChartDataLabel
|
||||
{
|
||||
Position = new Point { X = TooltipX(d) + offsetX, Y = TooltipY(d) + offsetY },
|
||||
TextAnchor = "middle",
|
||||
Text = Chart.ValueAxis.Format(Chart.ValueScale, Value(d))
|
||||
Text = chart.ValueAxis.Format(chart.ValueScale, Value(d))
|
||||
});
|
||||
}
|
||||
|
||||
@@ -793,12 +874,12 @@ namespace Radzen.Blazor
|
||||
/// <param name="defaultValue">The default value.</param>
|
||||
/// <param name="colorRange">The color range value.</param>
|
||||
/// <param name="value">The value of the item.</param>
|
||||
protected string PickColor(int index, IEnumerable<string> colors, string defaultValue = null, IList<SeriesColorRange> colorRange = null, double value = 0.0)
|
||||
protected string? PickColor(int index, IEnumerable<string>? colors, string? defaultValue = null, IList<SeriesColorRange>? colorRange = null, double value = 0.0)
|
||||
{
|
||||
if (colorRange != null)
|
||||
{
|
||||
var result = colorRange.Where(r => r.Min <= value && r.Max >= value).FirstOrDefault<SeriesColorRange>();
|
||||
return result != null ? result.Color : defaultValue;
|
||||
return result?.Color ?? defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -819,18 +900,20 @@ namespace Radzen.Blazor
|
||||
/// <inheritdoc />
|
||||
public async Task InvokeClick(EventCallback<SeriesClickEventArgs> handler, object data)
|
||||
{
|
||||
var category = Category(Chart.CategoryScale);
|
||||
var chart = RequireChart();
|
||||
var category = Category(chart.CategoryScale);
|
||||
var dataItem = (TItem)data;
|
||||
|
||||
await handler.InvokeAsync(new SeriesClickEventArgs
|
||||
{
|
||||
Data = data,
|
||||
Title = GetTitle(),
|
||||
Category = PropertyAccess.GetValue(data, CategoryProperty),
|
||||
Value = PropertyAccess.GetValue(data, ValueProperty),
|
||||
Category = !string.IsNullOrEmpty(CategoryProperty) ? PropertyAccess.GetValue(data, CategoryProperty) : null,
|
||||
Value = !string.IsNullOrEmpty(ValueProperty) ? PropertyAccess.GetValue(data, ValueProperty) : null,
|
||||
Point = new SeriesPoint
|
||||
{
|
||||
Category = category((TItem)data),
|
||||
Value = Value((TItem)data)
|
||||
Category = category(dataItem),
|
||||
Value = Value(dataItem)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -39,5 +39,5 @@ public class ChatMessage
|
||||
/// <summary>
|
||||
/// Gets or sets the role associated with the message (e.g., "user", "assistant").
|
||||
/// </summary>
|
||||
public string Role { get; set; }
|
||||
public string? Role { get; set; }
|
||||
}
|
||||
@@ -12,25 +12,25 @@ public class CompositeFilterDescriptor
|
||||
/// Gets or sets the name of the filtered property.
|
||||
/// </summary>
|
||||
/// <value>The property.</value>
|
||||
public string Property { get; set; }
|
||||
public string? Property { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the property type.
|
||||
/// </summary>
|
||||
/// <value>The property type.</value>
|
||||
public Type Type { get; set; }
|
||||
public Type? Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the filtered property.
|
||||
/// </summary>
|
||||
/// <value>The property.</value>
|
||||
public string FilterProperty { get; set; }
|
||||
public string? FilterProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value to filter by.
|
||||
/// </summary>
|
||||
/// <value>The filter value.</value>
|
||||
public object FilterValue { get; set; }
|
||||
public object? FilterValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the operator which will compare the property value with <see cref="FilterValue" />.
|
||||
@@ -48,6 +48,6 @@ public class CompositeFilterDescriptor
|
||||
/// Gets or sets the filters.
|
||||
/// </summary>
|
||||
/// <value>The filters.</value>
|
||||
public IEnumerable<CompositeFilterDescriptor> Filters { get; set; }
|
||||
public IEnumerable<CompositeFilterDescriptor>? Filters { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
using Microsoft.AspNetCore.Components.Web;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Radzen
|
||||
{
|
||||
@@ -43,13 +41,13 @@ namespace Radzen
|
||||
/// Gets or sets the navigation manager.
|
||||
/// </summary>
|
||||
/// <value>The navigation manager.</value>
|
||||
NavigationManager navigationManager { get; set; }
|
||||
NavigationManager? navigationManager { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContextMenuService"/> class.
|
||||
/// </summary>
|
||||
/// <param name="uriHelper">The URI helper.</param>
|
||||
public ContextMenuService(NavigationManager uriHelper)
|
||||
public ContextMenuService(NavigationManager? uriHelper)
|
||||
{
|
||||
navigationManager = uriHelper;
|
||||
|
||||
@@ -64,7 +62,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <param name="sender">The source of the event.</param>
|
||||
/// <param name="e">The <see cref="Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs"/> instance containing the event data.</param>
|
||||
private void UriHelper_OnLocationChanged(object sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e)
|
||||
private void UriHelper_OnLocationChanged(object? sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e)
|
||||
{
|
||||
this.OnNavigate?.Invoke();
|
||||
}
|
||||
@@ -72,17 +70,17 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// Occurs when [on navigate].
|
||||
/// </summary>
|
||||
public event Action OnNavigate;
|
||||
public event Action? OnNavigate;
|
||||
|
||||
/// <summary>
|
||||
/// Raises the Close event.
|
||||
/// </summary>
|
||||
public event Action OnClose;
|
||||
public event Action? OnClose;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [on open].
|
||||
/// </summary>
|
||||
public event Action<MouseEventArgs, ContextMenuOptions> OnOpen;
|
||||
public event Action<MouseEventArgs, ContextMenuOptions>? OnOpen;
|
||||
|
||||
/// <summary>
|
||||
/// Opens the specified arguments.
|
||||
@@ -90,7 +88,7 @@ namespace Radzen
|
||||
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <param name="click">The click.</param>
|
||||
public void Open(MouseEventArgs args, IEnumerable<ContextMenuItem> items, Action<MenuItemEventArgs> click = null)
|
||||
public void Open(MouseEventArgs args, IEnumerable<ContextMenuItem> items, Action<MenuItemEventArgs>? click = null)
|
||||
{
|
||||
var options = new ContextMenuOptions();
|
||||
|
||||
@@ -137,7 +135,11 @@ namespace Radzen
|
||||
/// </summary>
|
||||
public void Dispose()
|
||||
{
|
||||
navigationManager.LocationChanged -= UriHelper_OnLocationChanged;
|
||||
if (navigationManager != null)
|
||||
{
|
||||
navigationManager.LocationChanged -= UriHelper_OnLocationChanged;
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,18 +152,18 @@ namespace Radzen
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
public RenderFragment<ContextMenuService> ChildContent { get; set; }
|
||||
public RenderFragment<ContextMenuService>? ChildContent { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the items.
|
||||
/// </summary>
|
||||
/// <value>The items.</value>
|
||||
public IEnumerable<ContextMenuItem> Items { get; set; }
|
||||
public IEnumerable<ContextMenuItem>? Items { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the click.
|
||||
/// </summary>
|
||||
/// <value>The click.</value>
|
||||
public Action<MenuItemEventArgs> Click { get; set; }
|
||||
public Action<MenuItemEventArgs>? Click { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -173,12 +175,12 @@ namespace Radzen
|
||||
/// Gets or sets the options.
|
||||
/// </summary>
|
||||
/// <value>The options.</value>
|
||||
public ContextMenuOptions Options { get; set; }
|
||||
public ContextMenuOptions? Options { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the mouse event arguments.
|
||||
/// </summary>
|
||||
/// <value>The mouse event arguments.</value>
|
||||
public MouseEventArgs MouseEventArgs { get; set; }
|
||||
public MouseEventArgs? MouseEventArgs { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -190,32 +192,32 @@ namespace Radzen
|
||||
/// Gets or sets the text.
|
||||
/// </summary>
|
||||
/// <value>The text.</value>
|
||||
public string Text { get; set; }
|
||||
public string? Text { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
/// <value>The value.</value>
|
||||
public object Value { get; set; }
|
||||
public object? Value { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the icon.
|
||||
/// </summary>
|
||||
/// <value>The icon.</value>
|
||||
public string Icon { get; set; }
|
||||
public string? Icon { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the icon color.
|
||||
/// </summary>
|
||||
/// <value>The icon color.</value>
|
||||
public string IconColor { get; set; }
|
||||
public string? IconColor { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the image.
|
||||
/// </summary>
|
||||
/// <value>The image.</value>
|
||||
public string Image { get; set; }
|
||||
public string? Image { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the image style.
|
||||
/// </summary>
|
||||
/// <value>The image style.</value>
|
||||
public string ImageStyle { get; set; }
|
||||
public string? ImageStyle { get; set; }
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this instance is disabled.
|
||||
/// </summary>
|
||||
|
||||
@@ -18,25 +18,39 @@ public static class ConvertType
|
||||
/// <param name="type">The type.</param>
|
||||
/// <param name="culture">The culture.</param>
|
||||
/// <returns>System.Object</returns>
|
||||
public static object ChangeType(object value, Type type, CultureInfo culture = null)
|
||||
public static object? ChangeType(object value, Type type, CultureInfo? culture = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(type);
|
||||
|
||||
// CA1062: Validate 'value' is non-null before using it
|
||||
if (value == null)
|
||||
{
|
||||
if (Nullable.GetUnderlyingType(type) != null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
throw new ArgumentNullException(nameof(value));
|
||||
}
|
||||
|
||||
if (culture == null)
|
||||
{
|
||||
culture = CultureInfo.CurrentCulture;
|
||||
}
|
||||
if (value == null && Nullable.GetUnderlyingType(type) != null)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
|
||||
if ((Nullable.GetUnderlyingType(type) ?? type) == typeof(Guid) && value is string)
|
||||
{
|
||||
return Guid.Parse((string)value);
|
||||
}
|
||||
|
||||
if (Nullable.GetUnderlyingType(type)?.IsEnum == true)
|
||||
var underlyingEnumType = Nullable.GetUnderlyingType(type);
|
||||
if (underlyingEnumType?.IsEnum == true)
|
||||
{
|
||||
return Enum.Parse(Nullable.GetUnderlyingType(type), value.ToString());
|
||||
var valueString = value.ToString();
|
||||
if (valueString == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(value), "Enum value cannot be null.");
|
||||
}
|
||||
return Enum.Parse(underlyingEnumType, valueString);
|
||||
}
|
||||
|
||||
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(IEnumerable<>))
|
||||
|
||||
@@ -44,12 +44,12 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to use secure cookies.
|
||||
/// </summary>
|
||||
public bool IsSecure { get; set; } = false;
|
||||
public bool IsSecure { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the SameSite attribute for the cookie.
|
||||
/// </summary>
|
||||
public CookieSameSiteMode? SameSite { get; set; } = null;
|
||||
public CookieSameSiteMode? SameSite { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -64,13 +64,16 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CookieThemeService" /> class.
|
||||
/// </summary>
|
||||
public CookieThemeService(IJSRuntime jsRuntime, ThemeService themeService, IOptions<CookieThemeServiceOptions> options)
|
||||
public CookieThemeService(IJSRuntime jsRuntime, ThemeService themeService, IOptions<CookieThemeServiceOptions>? options)
|
||||
{
|
||||
this.jsRuntime = jsRuntime;
|
||||
this.themeService = themeService;
|
||||
this.options = options.Value;
|
||||
this.options = options?.Value ?? new CookieThemeServiceOptions();
|
||||
|
||||
themeService.ThemeChanged += OnThemeChanged;
|
||||
if (themeService != null)
|
||||
{
|
||||
themeService.ThemeChanged += OnThemeChanged;
|
||||
}
|
||||
|
||||
_ = InitializeAsync();
|
||||
}
|
||||
|
||||
@@ -47,14 +47,14 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
[Parameter]
|
||||
public string Name { get; set; }
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the placeholder.
|
||||
/// </summary>
|
||||
/// <value>The placeholder.</value>
|
||||
[Parameter]
|
||||
public string Placeholder { get; set; }
|
||||
public string? Placeholder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="DataBoundFormComponent{T}"/> is disabled.
|
||||
@@ -80,36 +80,36 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// The form
|
||||
/// </summary>
|
||||
IRadzenForm _form;
|
||||
IRadzenForm? form;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the form.
|
||||
/// </summary>
|
||||
/// <value>The form.</value>
|
||||
[CascadingParameter]
|
||||
public IRadzenForm Form
|
||||
public IRadzenForm? Form
|
||||
{
|
||||
get
|
||||
{
|
||||
return _form;
|
||||
return form;
|
||||
}
|
||||
set
|
||||
{
|
||||
_form = value;
|
||||
_form?.AddComponent(this);
|
||||
form = value;
|
||||
form?.AddComponent(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The value
|
||||
/// </summary>
|
||||
private T _value = default;
|
||||
private T? _value;
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
/// <value>The value.</value>
|
||||
[Parameter]
|
||||
public T Value
|
||||
public T? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -167,18 +167,18 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The text property.</value>
|
||||
[Parameter]
|
||||
public string TextProperty { get; set; }
|
||||
public string? TextProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The data
|
||||
/// </summary>
|
||||
IEnumerable _data = null;
|
||||
IEnumerable? _data;
|
||||
/// <summary>
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
[Parameter]
|
||||
public virtual IEnumerable Data
|
||||
public virtual IEnumerable? Data
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -208,7 +208,7 @@ namespace Radzen
|
||||
/// Gets the query.
|
||||
/// </summary>
|
||||
/// <value>The query.</value>
|
||||
protected virtual IQueryable Query
|
||||
protected virtual IQueryable? Query
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -220,7 +220,7 @@ namespace Radzen
|
||||
/// Gets or sets the search text
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string SearchText
|
||||
public string? SearchText
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -245,29 +245,30 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// The search text
|
||||
/// </summary>
|
||||
internal string searchText;
|
||||
internal string? searchText;
|
||||
|
||||
/// <summary>
|
||||
/// The view
|
||||
/// </summary>
|
||||
protected IQueryable _view = null;
|
||||
protected IQueryable? _view;
|
||||
/// <summary>
|
||||
/// Gets the view.
|
||||
/// </summary>
|
||||
/// <value>The view.</value>
|
||||
protected virtual IEnumerable View
|
||||
protected virtual IEnumerable? View
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_view == null && Query != null)
|
||||
var query = Query;
|
||||
if (_view == null && query != null)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(searchText))
|
||||
if (!string.IsNullOrEmpty(searchText) && !string.IsNullOrEmpty(TextProperty))
|
||||
{
|
||||
_view = Query.Where(TextProperty, searchText, FilterOperator, FilterCaseSensitivity);
|
||||
_view = query.Where(TextProperty, searchText, FilterOperator, FilterCaseSensitivity);
|
||||
}
|
||||
else
|
||||
{
|
||||
_view = (typeof(IQueryable).IsAssignableFrom(Data.GetType())) ? Query.Cast<object>().ToList().AsQueryable() : Query;
|
||||
_view = Data is IQueryable ? query.Cast<object>().ToList().AsQueryable() : query;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,14 +276,14 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
internal IEnumerable GetView() => View;
|
||||
internal IEnumerable? GetView() => View;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the edit context.
|
||||
/// </summary>
|
||||
/// <value>The edit context.</value>
|
||||
[CascadingParameter]
|
||||
public EditContext EditContext { get; set; }
|
||||
public EditContext? EditContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the field identifier.
|
||||
@@ -296,7 +297,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The value expression.</value>
|
||||
[Parameter]
|
||||
public Expression<Func<T>> ValueExpression { get; set; }
|
||||
public Expression<Func<T>>? ValueExpression { get; set; }
|
||||
/// <summary>
|
||||
/// Set parameters as an asynchronous operation.
|
||||
/// </summary>
|
||||
@@ -338,7 +339,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The <see cref="ValidationStateChangedEventArgs"/> instance containing the event data.</param>
|
||||
private void ValidationStateChanged(object sender, ValidationStateChangedEventArgs e)
|
||||
private void ValidationStateChanged(object? sender, ValidationStateChangedEventArgs e)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
@@ -356,13 +357,15 @@ namespace Radzen
|
||||
}
|
||||
|
||||
Form?.RemoveComponent(this);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value.
|
||||
/// </summary>
|
||||
/// <returns>System.Object.</returns>
|
||||
public virtual object GetValue()
|
||||
public virtual object? GetValue()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
@@ -386,13 +389,13 @@ namespace Radzen
|
||||
|
||||
/// <summary> Provides support for RadzenFormField integration. </summary>
|
||||
[CascadingParameter]
|
||||
public IFormFieldContext FormFieldContext { get; set; }
|
||||
public IFormFieldContext? FormFieldContext { get; set; }
|
||||
|
||||
/// <summary> Gets the current placeholder. Returns empty string if this component is inside a RadzenFormField.</summary>
|
||||
protected string CurrentPlaceholder => FormFieldContext?.AllowFloatingLabel == true ? " " : Placeholder;
|
||||
protected string? CurrentPlaceholder => FormFieldContext?.AllowFloatingLabel == true ? " " : Placeholder;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:ContextMenu" /> event.
|
||||
/// Handles the ContextMenu event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
|
||||
/// <returns>Task.</returns>
|
||||
|
||||
@@ -6,16 +6,16 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.CellContextMenu" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridCellMouseEventArgs<T> : Microsoft.AspNetCore.Components.Web.MouseEventArgs
|
||||
public class DataGridCellMouseEventArgs<T> : Microsoft.AspNetCore.Components.Web.MouseEventArgs where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the data item which the clicked DataGrid row represents.
|
||||
/// </summary>
|
||||
public T Data { get; internal set; }
|
||||
public T? Data { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the RadzenDataGridColumn which this cells represents.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
public RadzenDataGridColumn<T>? Column { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.CellRender" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridCellRenderEventArgs<T> : RowRenderEventArgs<T>
|
||||
public class DataGridCellRenderEventArgs<T> : RowRenderEventArgs<T> where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the RadzenDataGridColumn which this cells represents.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
public RadzenDataGridColumn<T>? Column { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ internal class DataGridChildData<T>
|
||||
/// <summary>
|
||||
/// Gets or sets the parent child data.
|
||||
/// </summary>
|
||||
internal DataGridChildData<T> ParentChildData { get; set; }
|
||||
internal DataGridChildData<T>? ParentChildData { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level.
|
||||
@@ -21,6 +21,6 @@ internal class DataGridChildData<T>
|
||||
/// <summary>
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
internal IEnumerable<T> Data { get; set; }
|
||||
internal IEnumerable<T>? Data { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -6,22 +6,22 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.Filter" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridColumnFilterEventArgs<T>
|
||||
public class DataGridColumnFilterEventArgs<T> where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the filtered RadzenDataGridColumn.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
public RadzenDataGridColumn<T>? Column { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the new filter value of the filtered column.
|
||||
/// </summary>
|
||||
public object FilterValue { get; internal set; }
|
||||
public object? FilterValue { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the new second filter value of the filtered column.
|
||||
/// </summary>
|
||||
public object SecondFilterValue { get; internal set; }
|
||||
public object? SecondFilterValue { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the new filter operator of the filtered column.
|
||||
|
||||
@@ -6,16 +6,16 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.Group" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridColumnGroupEventArgs<T>
|
||||
public class DataGridColumnGroupEventArgs<T> where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the grouped RadzenDataGridColumn.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
public RadzenDataGridColumn<T>? Column { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the group descriptor.
|
||||
/// </summary>
|
||||
public GroupDescriptor GroupDescriptor { get; internal set; }
|
||||
public GroupDescriptor? GroupDescriptor { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.ColumnReordered" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridColumnReorderedEventArgs<T>
|
||||
public class DataGridColumnReorderedEventArgs<T> where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the reordered RadzenDataGridColumn.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
public RadzenDataGridColumn<T>? Column { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the old index of the column.
|
||||
|
||||
@@ -6,17 +6,17 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.ColumnReordering" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridColumnReorderingEventArgs<T>
|
||||
public class DataGridColumnReorderingEventArgs<T> where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the reordered RadzenDataGridColumn.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
public RadzenDataGridColumn<T>? Column { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the reordered to RadzenDataGridColumn.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> ToColumn { get; internal set; }
|
||||
public RadzenDataGridColumn<T>? ToColumn { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value which will cancel the event.
|
||||
|
||||
@@ -6,12 +6,12 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.ColumnResized" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridColumnResizedEventArgs<T>
|
||||
public class DataGridColumnResizedEventArgs<T> where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the resized RadzenDataGridColumn.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
public RadzenDataGridColumn<T>? Column { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the new width of the resized column.
|
||||
|
||||
@@ -8,12 +8,12 @@ public class DataGridColumnSettings
|
||||
/// <summary>
|
||||
/// Property.
|
||||
/// </summary>
|
||||
public string UniqueID { get; set; }
|
||||
public string UniqueID { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Property.
|
||||
/// </summary>
|
||||
public string Property { get; set; }
|
||||
public string Property { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Visible.
|
||||
@@ -23,7 +23,7 @@ public class DataGridColumnSettings
|
||||
/// <summary>
|
||||
/// Width.
|
||||
/// </summary>
|
||||
public string Width { get; set; }
|
||||
public string Width { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// OrderIndex.
|
||||
@@ -43,7 +43,7 @@ public class DataGridColumnSettings
|
||||
/// <summary>
|
||||
/// FilterValue.
|
||||
/// </summary>
|
||||
public object FilterValue { get; set; }
|
||||
public object? FilterValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// FilterOperator.
|
||||
@@ -53,7 +53,7 @@ public class DataGridColumnSettings
|
||||
/// <summary>
|
||||
/// SecondFilterValue.
|
||||
/// </summary>
|
||||
public object SecondFilterValue { get; set; }
|
||||
public object? SecondFilterValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// SecondFilterOperator.
|
||||
@@ -68,7 +68,7 @@ public class DataGridColumnSettings
|
||||
/// <summary>
|
||||
/// CustomFilterExpression.
|
||||
/// </summary>
|
||||
public string CustomFilterExpression { get; set; }
|
||||
public string CustomFilterExpression { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the mode that determines whether the filter applies to any or all items in a collection.
|
||||
|
||||
@@ -6,12 +6,12 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.Sort" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridColumnSortEventArgs<T>
|
||||
public class DataGridColumnSortEventArgs<T> where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the sorted RadzenDataGridColumn.
|
||||
/// </summary>
|
||||
public RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
public RadzenDataGridColumn<T>? Column { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the new sort order of the sorted column.
|
||||
|
||||
@@ -12,12 +12,12 @@ public class DataGridLoadChildDataEventArgs<T>
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
public IEnumerable<T> Data { get; set; }
|
||||
public IEnumerable<T>? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item.
|
||||
/// </summary>
|
||||
/// <value>The item.</value>
|
||||
public T Item { get; internal set; }
|
||||
public T? Item { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -8,13 +8,13 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="Radzen.Blazor.RadzenDataGrid{TItem}.LoadColumnFilterData" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridLoadColumnFilterDataEventArgs<T>
|
||||
public class DataGridLoadColumnFilterDataEventArgs<T> where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
public IEnumerable Data { get; set; }
|
||||
public IEnumerable? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the total data count.
|
||||
@@ -37,17 +37,17 @@ public class DataGridLoadColumnFilterDataEventArgs<T>
|
||||
/// Gets the filter expression as a string.
|
||||
/// </summary>
|
||||
/// <value>The filter.</value>
|
||||
public string Filter { get; internal set; }
|
||||
public string? Filter { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets filter property used to limit and distinct values, if not set, args.Data are used as values.
|
||||
/// </summary>
|
||||
/// <value>The filter property.</value>
|
||||
public string Property { get; set; }
|
||||
public string? Property { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the RadzenDataGridColumn.
|
||||
/// </summary>
|
||||
public Radzen.Blazor.RadzenDataGridColumn<T> Column { get; internal set; }
|
||||
public Radzen.Blazor.RadzenDataGridColumn<T>? Column { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,6 @@ public class DataGridLoadSettingsEventArgs
|
||||
/// <summary>
|
||||
/// Gets or sets the settings.
|
||||
/// </summary>
|
||||
public DataGridSettings Settings { get; set; }
|
||||
public DataGridSettings? Settings { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -7,11 +7,11 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.PickedColumnsChanged" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridPickedColumnsChangedEventArgs<T>
|
||||
public class DataGridPickedColumnsChangedEventArgs<T> where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the picked columns.
|
||||
/// </summary>
|
||||
public IEnumerable<RadzenDataGridColumn<T>> Columns { get; internal set; }
|
||||
public IEnumerable<RadzenDataGridColumn<T>>? Columns { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -6,12 +6,12 @@ namespace Radzen;
|
||||
/// Supplies information about a <see cref="RadzenDataGrid{TItem}.Render" /> event that is being raised.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The data item type.</typeparam>
|
||||
public class DataGridRenderEventArgs<T>
|
||||
public class DataGridRenderEventArgs<T> where T : notnull
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the instance of the RadzenDataGrid component which has rendered.
|
||||
/// </summary>
|
||||
public RadzenDataGrid<T> Grid { get; internal set; }
|
||||
public RadzenDataGrid<T>? Grid { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this is the first time the RadzenDataGrid has rendered.
|
||||
|
||||
@@ -9,6 +9,6 @@ public class DataGridRowMouseEventArgs<T> : Microsoft.AspNetCore.Components.Web.
|
||||
/// <summary>
|
||||
/// Gets the data item which the clicked DataGrid row represents.
|
||||
/// </summary>
|
||||
public T Data { get; internal set; }
|
||||
public T? Data { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -10,12 +10,12 @@ public class DataGridSettings
|
||||
/// <summary>
|
||||
/// Columns.
|
||||
/// </summary>
|
||||
public IEnumerable<DataGridColumnSettings> Columns { get; set; }
|
||||
public IEnumerable<DataGridColumnSettings> Columns { get; set; } = System.Array.Empty<DataGridColumnSettings>();
|
||||
|
||||
/// <summary>
|
||||
/// Groups.
|
||||
/// </summary>
|
||||
public IEnumerable<GroupDescriptor> Groups { get; set; }
|
||||
public IEnumerable<GroupDescriptor> Groups { get; set; } = System.Array.Empty<GroupDescriptor>();
|
||||
|
||||
/// <summary>
|
||||
/// CurrentPage.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -50,14 +51,14 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (min != null)
|
||||
{
|
||||
var minDate = Convert.ToDateTime(min);
|
||||
var minDate = Convert.ToDateTime(min, CultureInfo.InvariantCulture);
|
||||
Input.Start = minDate.Ticks;
|
||||
Round = false;
|
||||
}
|
||||
|
||||
if (max != null)
|
||||
{
|
||||
var maxDate = Convert.ToDateTime(max);
|
||||
var maxDate = Convert.ToDateTime(max, CultureInfo.InvariantCulture);
|
||||
Input.End = maxDate.Ticks;
|
||||
Round = false;
|
||||
}
|
||||
|
||||
@@ -6,9 +6,9 @@ namespace Radzen;
|
||||
/// <summary>
|
||||
/// Utility class for debouncing and throttling function calls.
|
||||
/// </summary>
|
||||
internal class Debouncer
|
||||
internal class Debouncer : IDisposable
|
||||
{
|
||||
private System.Timers.Timer timer;
|
||||
private System.Timers.Timer? timer;
|
||||
private DateTime timerStarted { get; set; } = DateTime.UtcNow.AddYears(-1);
|
||||
|
||||
/// <summary>
|
||||
@@ -86,4 +86,15 @@ internal class Debouncer
|
||||
timer.Start();
|
||||
timerStarted = curTime;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Dispose()
|
||||
{
|
||||
if(timer != null)
|
||||
{
|
||||
timer.Stop();
|
||||
timer.Dispose();
|
||||
timer = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ namespace Radzen
|
||||
/// </example>
|
||||
public class DialogService : IDisposable
|
||||
{
|
||||
private DotNetObjectReference<DialogService> reference;
|
||||
internal DotNetObjectReference<DialogService> Reference
|
||||
private DotNetObjectReference<DialogService>? reference;
|
||||
internal DotNetObjectReference<DialogService>? Reference
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -59,15 +59,15 @@ namespace Radzen
|
||||
/// Gets or sets the URI helper.
|
||||
/// </summary>
|
||||
/// <value>The URI helper.</value>
|
||||
NavigationManager UriHelper { get; set; }
|
||||
IJSRuntime JSRuntime { get; set; }
|
||||
NavigationManager? UriHelper { get; set; }
|
||||
IJSRuntime? JSRuntime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DialogService"/> class.
|
||||
/// </summary>
|
||||
/// <param name="uriHelper">The URI helper.</param>
|
||||
/// <param name="jsRuntime">IJSRuntime instance.</param>
|
||||
public DialogService(NavigationManager uriHelper, IJSRuntime jsRuntime)
|
||||
public DialogService(NavigationManager? uriHelper, IJSRuntime? jsRuntime)
|
||||
{
|
||||
UriHelper = uriHelper;
|
||||
JSRuntime = jsRuntime;
|
||||
@@ -78,9 +78,9 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private void UriHelper_OnLocationChanged(object sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e)
|
||||
private void UriHelper_OnLocationChanged(object? sender, Microsoft.AspNetCore.Components.Routing.LocationChangedEventArgs e)
|
||||
{
|
||||
while (dialogs.Any())
|
||||
while (dialogs.Count > 0)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
@@ -94,27 +94,27 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// Raises the Close event.
|
||||
/// </summary>
|
||||
public event Action<dynamic> OnClose;
|
||||
public event Action<dynamic>? OnClose;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when [on refresh].
|
||||
/// </summary>
|
||||
public event Action OnRefresh;
|
||||
public event Action? OnRefresh;
|
||||
|
||||
/// <summary>
|
||||
/// Occurs when a new dialog is open.
|
||||
/// </summary>
|
||||
public event Action<string, Type, Dictionary<string, object>, DialogOptions> OnOpen;
|
||||
public event Action<string?, Type, Dictionary<string, object>, DialogOptions>? OnOpen;
|
||||
|
||||
/// <summary>
|
||||
/// Raises the Close event for the side dialog
|
||||
/// </summary>
|
||||
public event Action<dynamic> OnSideClose;
|
||||
public event Action<dynamic>? OnSideClose;
|
||||
|
||||
/// <summary>
|
||||
/// Raises the Open event for the side dialog
|
||||
/// </summary>
|
||||
public event Action<Type, Dictionary<string, object>, SideDialogOptions> OnSideOpen;
|
||||
public event Action<Type, Dictionary<string, object>, SideDialogOptions>? OnSideOpen;
|
||||
|
||||
/// <summary>
|
||||
/// Opens a dialog with the specified arguments.
|
||||
@@ -123,7 +123,7 @@ namespace Radzen
|
||||
/// <param name="title">The text displayed in the title bar of the dialog.</param>
|
||||
/// <param name="parameters">The dialog parameters.</param>
|
||||
/// <param name="options">The dialog options.</param>
|
||||
public virtual void Open<T>(string title, Dictionary<string, object> parameters = null, DialogOptions options = null) where T : ComponentBase
|
||||
public virtual void Open<T>(string title, Dictionary<string, object>? parameters = null, DialogOptions? options = null) where T : ComponentBase
|
||||
{
|
||||
OpenDialog<T>(title, parameters, options);
|
||||
}
|
||||
@@ -135,7 +135,7 @@ namespace Radzen
|
||||
/// <param name="componentType">The type of the component to be displayed in the dialog. Must inherit from <see cref="ComponentBase"/>.</param>
|
||||
/// <param name="parameters">The dialog parameters.</param>
|
||||
/// <param name="options">The dialog options.</param>
|
||||
public virtual void Open(string title, Type componentType, Dictionary<string, object> parameters = null, DialogOptions options = null)
|
||||
public virtual void Open(string title, Type componentType, Dictionary<string, object>? parameters = null, DialogOptions? options = null)
|
||||
{
|
||||
if (!typeof(ComponentBase).IsAssignableFrom(componentType))
|
||||
{
|
||||
@@ -143,8 +143,12 @@ namespace Radzen
|
||||
}
|
||||
|
||||
var method = GetType().GetMethod(nameof(OpenDialog), BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (method == null)
|
||||
{
|
||||
throw new InvalidOperationException("OpenDialog method not found.");
|
||||
}
|
||||
|
||||
method.MakeGenericMethod(componentType).Invoke(this, new object[] { title, parameters, options });
|
||||
method.MakeGenericMethod(componentType).Invoke(this, new object[] { title, parameters!, options! });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -159,7 +163,7 @@ namespace Radzen
|
||||
/// The tasks
|
||||
/// </summary>
|
||||
protected List<TaskCompletionSource<dynamic>> tasks = new List<TaskCompletionSource<dynamic>>();
|
||||
private TaskCompletionSource<dynamic> sideDialogResultTask;
|
||||
private TaskCompletionSource<dynamic>? sideDialogResultTask;
|
||||
|
||||
/// <summary>
|
||||
/// Opens a dialog with the specified arguments.
|
||||
@@ -169,7 +173,7 @@ namespace Radzen
|
||||
/// <param name="parameters">The dialog parameters. Passed as property values of <typeparamref name="T" />.</param>
|
||||
/// <param name="options">The dialog options.</param>
|
||||
/// <returns>The value passed as argument to <see cref="Close" />.</returns>
|
||||
public virtual Task<dynamic> OpenAsync<T>(string title, Dictionary<string, object> parameters = null, DialogOptions options = null) where T : ComponentBase
|
||||
public virtual Task<dynamic> OpenAsync<T>(string title, Dictionary<string, object>? parameters = null, DialogOptions? options = null) where T : ComponentBase
|
||||
{
|
||||
var task = new TaskCompletionSource<dynamic>();
|
||||
tasks.Add(task);
|
||||
@@ -188,7 +192,7 @@ namespace Radzen
|
||||
/// <param name="options">The dialog options.</param>
|
||||
/// <returns>A task that represents the result passed as an argument to <see cref="Close"/>.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown if <paramref name="componentType"/> does not inherit from <see cref="ComponentBase"/>.</exception>
|
||||
public virtual Task<dynamic> OpenAsync(string title, Type componentType, Dictionary<string, object> parameters = null, DialogOptions options = null)
|
||||
public virtual Task<dynamic> OpenAsync(string title, Type componentType, Dictionary<string, object>? parameters = null, DialogOptions? options = null)
|
||||
{
|
||||
if (!typeof(ComponentBase).IsAssignableFrom(componentType))
|
||||
{
|
||||
@@ -199,8 +203,12 @@ namespace Radzen
|
||||
tasks.Add(task);
|
||||
|
||||
var method = GetType().GetMethod(nameof(OpenDialog), BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (method == null)
|
||||
{
|
||||
throw new InvalidOperationException("OpenDialog method not found.");
|
||||
}
|
||||
|
||||
method.MakeGenericMethod(componentType).Invoke(this, new object[] { title, parameters, options });
|
||||
method.MakeGenericMethod(componentType).Invoke(this, new object[] { title, parameters!, options! });
|
||||
|
||||
return task.Task;
|
||||
}
|
||||
@@ -214,7 +222,7 @@ namespace Radzen
|
||||
/// <param name="parameters">The dialog parameters. Passed as property values of <typeparamref name="T"/></param>
|
||||
/// <param name="options">The side dialog options.</param>
|
||||
/// <returns>A task that completes when the dialog is closed or a new one opened</returns>
|
||||
public Task<dynamic> OpenSideAsync<T>(string title, Dictionary<string, object> parameters = null, SideDialogOptions options = null)
|
||||
public Task<dynamic> OpenSideAsync<T>(string title, Dictionary<string, object>? parameters = null, SideDialogOptions? options = null)
|
||||
where T : ComponentBase
|
||||
{
|
||||
CloseSide();
|
||||
@@ -238,7 +246,7 @@ namespace Radzen
|
||||
/// <param name="options">The side dialog options.</param>
|
||||
/// <returns>A task that represents the result passed as an argument to <see cref="CloseSide"/>.</returns>
|
||||
/// <exception cref="ArgumentException">Thrown if <paramref name="componentType"/> does not inherit from <see cref="ComponentBase"/>.</exception>
|
||||
public Task<dynamic> OpenSideAsync(string title, Type componentType, Dictionary<string, object> parameters = null, SideDialogOptions options = null)
|
||||
public Task<dynamic> OpenSideAsync(string title, Type componentType, Dictionary<string, object>? parameters = null, SideDialogOptions? options = null)
|
||||
{
|
||||
if (!typeof(ComponentBase).IsAssignableFrom(componentType))
|
||||
{
|
||||
@@ -267,7 +275,7 @@ namespace Radzen
|
||||
/// <param name="title">The text displayed in the title bar of the side dialog.</param>
|
||||
/// <param name="parameters">The dialog parameters. Passed as property values of <typeparamref name="T"/></param>
|
||||
/// <param name="options">The side dialog options.</param>
|
||||
public void OpenSide<T>(string title, Dictionary<string, object> parameters = null, SideDialogOptions options = null)
|
||||
public void OpenSide<T>(string title, Dictionary<string, object>? parameters = null, SideDialogOptions? options = null)
|
||||
where T : ComponentBase
|
||||
{
|
||||
CloseSide();
|
||||
@@ -289,7 +297,7 @@ namespace Radzen
|
||||
/// <param name="parameters">The dialog parameters, passed as property values of the specified component.</param>
|
||||
/// <param name="options">The side dialog options.</param>
|
||||
/// <exception cref="ArgumentException">Thrown if <paramref name="componentType"/> does not inherit from <see cref="ComponentBase"/>.</exception>
|
||||
public void OpenSide(string title, Type componentType, Dictionary<string, object> parameters = null, SideDialogOptions options = null)
|
||||
public void OpenSide(string title, Type componentType, Dictionary<string, object>? parameters = null, SideDialogOptions? options = null)
|
||||
{
|
||||
if (!typeof(ComponentBase).IsAssignableFrom(componentType))
|
||||
{
|
||||
@@ -312,7 +320,7 @@ namespace Radzen
|
||||
/// Closes the side dialog
|
||||
/// </summary>
|
||||
/// <param name="result">The result of the Dialog</param>
|
||||
public virtual void CloseSide(dynamic result = null)
|
||||
public virtual void CloseSide(dynamic? result = null)
|
||||
{
|
||||
if (sideDialogResultTask?.Task.IsCompleted == false)
|
||||
{
|
||||
@@ -322,7 +330,7 @@ namespace Radzen
|
||||
OnSideClose?.Invoke(result);
|
||||
}
|
||||
|
||||
private TaskCompletionSource sideDialogCloseTask;
|
||||
private TaskCompletionSource? sideDialogCloseTask;
|
||||
|
||||
internal void OnSideCloseComplete()
|
||||
{
|
||||
@@ -334,7 +342,7 @@ namespace Radzen
|
||||
/// Closes the side dialog and waits for the closing animation to finish.
|
||||
/// </summary>
|
||||
/// <param name="result">The result of the Dialog</param>
|
||||
public async Task CloseSideAsync(dynamic result = null)
|
||||
public async Task CloseSideAsync(dynamic? result = null)
|
||||
{
|
||||
sideDialogCloseTask = new TaskCompletionSource();
|
||||
|
||||
@@ -351,7 +359,7 @@ namespace Radzen
|
||||
/// <param name="options">The dialog options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The value passed as argument to <see cref="Close" />.</returns>
|
||||
public virtual Task<dynamic> OpenAsync(string title, RenderFragment<DialogService> childContent, DialogOptions options = null, CancellationToken? cancellationToken = null)
|
||||
public virtual Task<dynamic> OpenAsync(string title, RenderFragment<DialogService> childContent, DialogOptions? options = null, CancellationToken? cancellationToken = null)
|
||||
{
|
||||
var task = new TaskCompletionSource<dynamic>();
|
||||
|
||||
@@ -377,7 +385,7 @@ namespace Radzen
|
||||
/// <param name="options">The dialog options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The value passed as argument to <see cref="Close" />.</returns>
|
||||
public virtual Task<dynamic> OpenAsync(RenderFragment<DialogService> titleContent, RenderFragment<DialogService> childContent, DialogOptions options = null, CancellationToken? cancellationToken = null)
|
||||
public virtual Task<dynamic> OpenAsync(RenderFragment<DialogService> titleContent, RenderFragment<DialogService> childContent, DialogOptions? options = null, CancellationToken? cancellationToken = null)
|
||||
{
|
||||
var task = new TaskCompletionSource<dynamic>();
|
||||
|
||||
@@ -402,7 +410,7 @@ namespace Radzen
|
||||
/// <param name="title">The text displayed in the title bar of the dialog.</param>
|
||||
/// <param name="childContent">The content displayed in the dialog.</param>
|
||||
/// <param name="options">The dialog options.</param>
|
||||
public virtual void Open(string title, RenderFragment<DialogService> childContent, DialogOptions options = null)
|
||||
public virtual void Open(string title, RenderFragment<DialogService> childContent, DialogOptions? options = null)
|
||||
{
|
||||
options = options ?? new DialogOptions();
|
||||
|
||||
@@ -416,12 +424,13 @@ namespace Radzen
|
||||
/// </summary>
|
||||
protected List<object> dialogs = new List<object>();
|
||||
|
||||
internal void OpenDialog<T>(string title, Dictionary<string, object> parameters, DialogOptions options)
|
||||
internal void OpenDialog<T>(string? title, Dictionary<string, object>? parameters, DialogOptions? options)
|
||||
{
|
||||
dialogs.Add(new object());
|
||||
|
||||
// Validate and set default values for the dialog options
|
||||
options ??= new();
|
||||
parameters ??= new Dictionary<string, object>();
|
||||
options.Width = !String.IsNullOrEmpty(options.Width) ? options.Width : "600px";
|
||||
options.Left = !String.IsNullOrEmpty(options.Left) ? options.Left : "";
|
||||
options.Top = !String.IsNullOrEmpty(options.Top) ? options.Top : "";
|
||||
@@ -440,7 +449,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <param name="result">The result.</param>
|
||||
[JSInvokable("DialogService.Close")]
|
||||
public virtual void Close(dynamic result = null)
|
||||
public virtual void Close(dynamic? result = null)
|
||||
{
|
||||
var dialog = dialogs.LastOrDefault();
|
||||
|
||||
@@ -464,7 +473,7 @@ namespace Radzen
|
||||
reference?.Dispose();
|
||||
reference = null;
|
||||
|
||||
UriHelper.LocationChanged -= UriHelper_OnLocationChanged;
|
||||
UriHelper?.LocationChanged -= UriHelper_OnLocationChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -475,7 +484,7 @@ namespace Radzen
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns><c>true</c> if the user clicked the OK button, <c>false</c> otherwise.</returns>
|
||||
public virtual async Task<bool?> Confirm(string message = "Confirm?", string title = "Confirm", ConfirmOptions options = null, CancellationToken? cancellationToken = null)
|
||||
public virtual async Task<bool?> Confirm(string message = "Confirm?", string title = "Confirm", ConfirmOptions? options = null, CancellationToken? cancellationToken = null)
|
||||
{
|
||||
// Validate and set default values for the dialog options
|
||||
options ??= new();
|
||||
@@ -524,7 +533,7 @@ namespace Radzen
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns><c>true</c> if the user clicked the OK button, <c>false</c> otherwise.</returns>
|
||||
public virtual async Task<bool?> Confirm(RenderFragment message, string title = "Confirm", ConfirmOptions options = null, CancellationToken? cancellationToken = null)
|
||||
public virtual async Task<bool?> Confirm(RenderFragment message, string title = "Confirm", ConfirmOptions? options = null, CancellationToken? cancellationToken = null)
|
||||
{
|
||||
// Validate and set default values for the dialog options
|
||||
options ??= new();
|
||||
@@ -573,7 +582,7 @@ namespace Radzen
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns><c>true</c> if the user clicked the OK button, <c>false</c> otherwise.</returns>
|
||||
public virtual async Task<bool?> Alert(string message = "", string title = "Message", AlertOptions options = null, CancellationToken? cancellationToken = null)
|
||||
public virtual async Task<bool?> Alert(string message = "", string title = "Message", AlertOptions? options = null, CancellationToken? cancellationToken = null)
|
||||
{
|
||||
// Validate and set default values for the dialog options
|
||||
options ??= new();
|
||||
@@ -616,7 +625,7 @@ namespace Radzen
|
||||
/// <param name="options">The options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns><c>true</c> if the user clicked the OK button, <c>false</c> otherwise.</returns>
|
||||
public virtual async Task<bool?> Alert(RenderFragment message, string title = "Message", AlertOptions options = null, CancellationToken? cancellationToken = null)
|
||||
public virtual async Task<bool?> Alert(RenderFragment message, string title = "Message", AlertOptions? options = null, CancellationToken? cancellationToken = null)
|
||||
{
|
||||
// Validate and set default values for the dialog options
|
||||
options ??= new();
|
||||
@@ -660,7 +669,7 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// Occurs when a property value changes.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="PropertyChanged" /> event.
|
||||
@@ -707,12 +716,12 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private string width;
|
||||
private string? width;
|
||||
/// <summary>
|
||||
/// Gets or sets the width of the dialog.
|
||||
/// </summary>
|
||||
/// <value>The width.</value>
|
||||
public string Width
|
||||
public string? Width
|
||||
{
|
||||
get => width;
|
||||
set
|
||||
@@ -725,12 +734,12 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private string height;
|
||||
private string? height;
|
||||
/// <summary>
|
||||
/// Gets or sets the height of the dialog.
|
||||
/// </summary>
|
||||
/// <value>The height.</value>
|
||||
public string Height
|
||||
public string? Height
|
||||
{
|
||||
get => height;
|
||||
set
|
||||
@@ -743,12 +752,12 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private string style;
|
||||
private string? style;
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS style of the dialog
|
||||
/// </summary>
|
||||
/// <value>The style.</value>
|
||||
public string Style
|
||||
public string? Style
|
||||
{
|
||||
get => style;
|
||||
set
|
||||
@@ -761,7 +770,7 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private bool closeDialogOnOverlayClick = false;
|
||||
private bool closeDialogOnOverlayClick;
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the dialog should be closed by clicking the overlay.
|
||||
/// </summary>
|
||||
@@ -779,11 +788,11 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private string cssClass;
|
||||
private string? cssClass;
|
||||
/// <summary>
|
||||
/// Gets or sets dialog box custom class
|
||||
/// </summary>
|
||||
public string CssClass
|
||||
public string? CssClass
|
||||
{
|
||||
get => cssClass;
|
||||
set
|
||||
@@ -796,11 +805,11 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private string wrapperCssClass;
|
||||
private string? wrapperCssClass;
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS classes added to the dialog's wrapper element.
|
||||
/// </summary>
|
||||
public string WrapperCssClass
|
||||
public string? WrapperCssClass
|
||||
{
|
||||
get => wrapperCssClass;
|
||||
set
|
||||
@@ -813,11 +822,11 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private string contentCssClass;
|
||||
private string? contentCssClass;
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS classes added to the dialog's content element.
|
||||
/// </summary>
|
||||
public string ContentCssClass
|
||||
public string? ContentCssClass
|
||||
{
|
||||
get => contentCssClass;
|
||||
set
|
||||
@@ -830,7 +839,7 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private int closeTabIndex = 0;
|
||||
private int closeTabIndex;
|
||||
/// <summary>
|
||||
/// Gets or sets a value the dialog escape tabindex. Set to <c>0</c> by default.
|
||||
/// </summary>
|
||||
@@ -847,14 +856,14 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private RenderFragment<DialogService> titleContent;
|
||||
private RenderFragment<DialogService>? titleContent;
|
||||
private bool resizable;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title content.
|
||||
/// </summary>
|
||||
/// <value>The title content.</value>
|
||||
public RenderFragment<DialogService> TitleContent
|
||||
public RenderFragment<DialogService>? TitleContent
|
||||
{
|
||||
get => titleContent;
|
||||
set
|
||||
@@ -890,12 +899,12 @@ namespace Radzen
|
||||
/// </summary>
|
||||
public class SideDialogOptions : DialogOptionsBase
|
||||
{
|
||||
private string title;
|
||||
private string? title;
|
||||
|
||||
/// <summary>
|
||||
/// The title displayed on the dialog.
|
||||
/// </summary>
|
||||
public string Title
|
||||
public string? Title
|
||||
{
|
||||
get => title;
|
||||
set
|
||||
@@ -945,7 +954,7 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private bool autoFocusFirstElement = false;
|
||||
private bool autoFocusFirstElement;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to focus the first focusable HTML element. Set to <c>true</c> by default.
|
||||
@@ -1061,26 +1070,26 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The icon.</value>
|
||||
|
||||
public string Icon { get; set; }
|
||||
public string? Icon { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the icon color in Title.
|
||||
/// </summary>
|
||||
/// <value>The icon color.</value>
|
||||
|
||||
public string IconColor { get; set; }
|
||||
public string? IconColor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the CSS style of the Icon in Title.
|
||||
/// </summary>
|
||||
public string IconStyle { get; set; } = "margin-right: 0.75rem";
|
||||
|
||||
private Action<Size> resize;
|
||||
private Action<Size>? resize;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the change.
|
||||
/// </summary>
|
||||
/// <value>The change.</value>
|
||||
public Action<Size> Resize
|
||||
public Action<Size>? Resize
|
||||
{
|
||||
get => resize;
|
||||
set
|
||||
@@ -1112,13 +1121,13 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private Action<Point> drag;
|
||||
private Action<Point>? drag;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the change.
|
||||
/// </summary>
|
||||
/// <value>The change.</value>
|
||||
public Action<Point> Drag
|
||||
public Action<Point>? Drag
|
||||
{
|
||||
get => drag;
|
||||
set
|
||||
@@ -1131,13 +1140,13 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private string left;
|
||||
private string? left;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the X coordinate of the dialog. Maps to the <c>left</c> CSS attribute.
|
||||
/// </summary>
|
||||
/// <value>The left.</value>
|
||||
public string Left
|
||||
public string? Left
|
||||
{
|
||||
get => left;
|
||||
set
|
||||
@@ -1150,13 +1159,13 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private string top;
|
||||
private string? top;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Y coordinate of the dialog. Maps to the <c>top</c> CSS attribute.
|
||||
/// </summary>
|
||||
/// <value>The top.</value>
|
||||
public string Top
|
||||
public string? Top
|
||||
{
|
||||
get => top;
|
||||
set
|
||||
@@ -1169,13 +1178,13 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private string bottom;
|
||||
private string? bottom;
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the <c>bottom</c> CSS attribute.
|
||||
/// </summary>
|
||||
/// <value>The bottom.</value>
|
||||
public string Bottom
|
||||
public string? Bottom
|
||||
{
|
||||
get => bottom;
|
||||
set
|
||||
@@ -1188,13 +1197,13 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private RenderFragment<DialogService> childContent;
|
||||
private RenderFragment<DialogService>? childContent;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the child content.
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
public RenderFragment<DialogService> ChildContent
|
||||
public RenderFragment<DialogService>? ChildContent
|
||||
{
|
||||
get => childContent;
|
||||
set
|
||||
@@ -1251,12 +1260,12 @@ namespace Radzen
|
||||
/// </summary>
|
||||
public class AlertOptions : DialogOptions
|
||||
{
|
||||
private string okButtonText;
|
||||
private string? okButtonText;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text of the OK button.
|
||||
/// </summary>
|
||||
public string OkButtonText
|
||||
public string? OkButtonText
|
||||
{
|
||||
get => okButtonText;
|
||||
set
|
||||
@@ -1275,12 +1284,12 @@ namespace Radzen
|
||||
/// </summary>
|
||||
public class ConfirmOptions : AlertOptions
|
||||
{
|
||||
private string cancelButtonText;
|
||||
private string? cancelButtonText;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text of the Cancel button.
|
||||
/// </summary>
|
||||
public string CancelButtonText
|
||||
public string? CancelButtonText
|
||||
{
|
||||
get => cancelButtonText;
|
||||
set
|
||||
@@ -1299,13 +1308,13 @@ namespace Radzen
|
||||
/// </summary>
|
||||
public class Dialog : INotifyPropertyChanged
|
||||
{
|
||||
private string title;
|
||||
private string? title;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the title.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
public string Title
|
||||
public string? Title
|
||||
{
|
||||
get => title;
|
||||
set
|
||||
@@ -1318,13 +1327,13 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private Type type;
|
||||
private Type? type;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type.
|
||||
/// </summary>
|
||||
/// <value>The type.</value>
|
||||
public Type Type
|
||||
public Type? Type
|
||||
{
|
||||
get => type;
|
||||
set
|
||||
@@ -1337,13 +1346,13 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private Dictionary<string, object> parameters;
|
||||
private Dictionary<string, object>? parameters;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameters.
|
||||
/// </summary>
|
||||
/// <value>The parameters.</value>
|
||||
public Dictionary<string, object> Parameters
|
||||
public Dictionary<string, object>? Parameters
|
||||
{
|
||||
get => parameters;
|
||||
set
|
||||
@@ -1356,13 +1365,13 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
private DialogOptions options;
|
||||
private DialogOptions? options;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the options.
|
||||
/// </summary>
|
||||
/// <value>The options.</value>
|
||||
public DialogOptions Options
|
||||
public DialogOptions? Options
|
||||
{
|
||||
get => options;
|
||||
set
|
||||
@@ -1378,7 +1387,7 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// Occurs when a property value changes.
|
||||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
public event PropertyChangedEventHandler? PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Raises the <see cref="PropertyChanged"/> event.
|
||||
|
||||
73
Radzen.Blazor/Directory.Build.props
Normal file
73
Radzen.Blazor/Directory.Build.props
Normal file
@@ -0,0 +1,73 @@
|
||||
<Project>
|
||||
<!--
|
||||
Common build properties for all projects in the Radzen.Blazor solution.
|
||||
|
||||
To use this file:
|
||||
1. Rename to Directory.Build.props (remove .sample extension)
|
||||
2. Adjust settings based on your needs
|
||||
3. Review the analyzer settings in .editorconfig
|
||||
|
||||
This file will be automatically imported by all projects in subdirectories.
|
||||
-->
|
||||
|
||||
<PropertyGroup Label="Language Configuration">
|
||||
<!-- Use latest C# language features -->
|
||||
<LangVersion>latest</LangVersion>
|
||||
|
||||
<!-- Do NOT enable implicit usings - explicit imports preferred for library code -->
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
|
||||
<Nullable>enable</Nullable>
|
||||
<NoWarn>CA2007</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Code Analysis Configuration">
|
||||
<!-- Enable .NET code analyzers -->
|
||||
<AnalysisLevel>latest</AnalysisLevel>
|
||||
<EnableNETAnalyzers>true</EnableNETAnalyzers>
|
||||
|
||||
<!-- Run analyzers during build and in IDE -->
|
||||
<RunAnalyzersDuringBuild>true</RunAnalyzersDuringBuild>
|
||||
<RunAnalyzersDuringLiveAnalysis>true</RunAnalyzersDuringLiveAnalysis>
|
||||
|
||||
<!-- Don't enforce code style in build (yet) - just show warnings -->
|
||||
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
|
||||
|
||||
<!-- Don't treat warnings as errors (yet) - too many to fix immediately -->
|
||||
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
|
||||
|
||||
<!-- Report all analyzer diagnostics -->
|
||||
<AnalysisMode>All</AnalysisMode>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Build Quality">
|
||||
<!-- Enable deterministic builds for reproducibility -->
|
||||
<Deterministic>true</Deterministic>
|
||||
|
||||
<!-- Enable deterministic builds in CI/CD -->
|
||||
<ContinuousIntegrationBuild Condition="'$(CI)' == 'true'">true</ContinuousIntegrationBuild>
|
||||
|
||||
<!-- Embed source files for better debugging -->
|
||||
<EmbedAllSources>true</EmbedAllSources>
|
||||
<DebugType>embedded</DebugType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Demos and Tests Project Configuration" Condition="$(MSBuildProjectName.Contains('Demos')) OR $(MSBuildProjectName.Contains('Tests'))">
|
||||
<!-- Demo projects and Tests should not be packable -->
|
||||
<IsPackable>false</IsPackable>
|
||||
|
||||
<!-- DISABLE ALL ANALYZERS FOR DEMO PROJECTS AND TESTS -->
|
||||
<EnableNETAnalyzers>false</EnableNETAnalyzers>
|
||||
<RunAnalyzersDuringBuild>false</RunAnalyzersDuringBuild>
|
||||
<RunAnalyzersDuringLiveAnalysis>false</RunAnalyzersDuringLiveAnalysis>
|
||||
<EnforceCodeStyleInBuild>false</EnforceCodeStyleInBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Label="Performance">
|
||||
<!-- Optimize startup time -->
|
||||
<TieredCompilation>true</TieredCompilation>
|
||||
<TieredCompilationQuickJit>true</TieredCompilationQuickJit>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
using Microsoft.JSInterop;
|
||||
using Radzen.Blazor;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
@@ -22,12 +21,12 @@ namespace Radzen
|
||||
[Parameter]
|
||||
public int VirtualizationOverscanCount { get; set; }
|
||||
|
||||
internal Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<object> virtualize;
|
||||
internal Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<object>? virtualize;
|
||||
|
||||
/// <summary>
|
||||
/// The Virtualize instance.
|
||||
/// </summary>
|
||||
public Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<object> Virtualize
|
||||
public Microsoft.AspNetCore.Components.Web.Virtualization.Virtualize<object>? Virtualize
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -35,12 +34,12 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
List<object> virtualItems;
|
||||
List<object>? virtualItems;
|
||||
|
||||
private async ValueTask<Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<object>> LoadItems(Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderRequest request)
|
||||
{
|
||||
var data = Data != null ? Data.Cast<object>() : Enumerable.Empty<object>();
|
||||
var view = (LoadData.HasDelegate ? data : View).Cast<object>().AsQueryable();
|
||||
var view = (LoadData.HasDelegate ? data : View)?.Cast<object>().AsQueryable() ?? Enumerable.Empty<object>().AsQueryable();
|
||||
var totalItemsCount = LoadData.HasDelegate ? Count : view.Count();
|
||||
var top = request.Count;
|
||||
|
||||
@@ -54,7 +53,7 @@ namespace Radzen
|
||||
await LoadData.InvokeAsync(new Radzen.LoadDataArgs() { Skip = request.StartIndex, Top = top, Filter = searchText });
|
||||
}
|
||||
|
||||
virtualItems = (LoadData.HasDelegate ? Data : view.Skip(request.StartIndex).Take(top)).Cast<object>().ToList();
|
||||
virtualItems = (LoadData.HasDelegate ? (Data ?? Enumerable.Empty<object>()) : view.Skip(request.StartIndex).Take(top)).Cast<object>().ToList();
|
||||
|
||||
return new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderResult<object>(virtualItems, LoadData.HasDelegate ? Count : totalItemsCount);
|
||||
}
|
||||
@@ -105,13 +104,13 @@ namespace Radzen
|
||||
builder.AddAttribute(1, "ItemsProvider", new Microsoft.AspNetCore.Components.Web.Virtualization.ItemsProviderDelegate<object>(LoadItems));
|
||||
builder.AddAttribute(2, "ChildContent", (RenderFragment<object>)((context) =>
|
||||
{
|
||||
return (RenderFragment)((b) =>
|
||||
return b =>
|
||||
{
|
||||
RenderItem(b, context);
|
||||
});
|
||||
};
|
||||
}));
|
||||
|
||||
if (VirtualizationOverscanCount != default(int))
|
||||
if (VirtualizationOverscanCount != default)
|
||||
{
|
||||
builder.AddAttribute(3, "OverscanCount", VirtualizationOverscanCount);
|
||||
}
|
||||
@@ -122,9 +121,13 @@ namespace Radzen
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var item in LoadData.HasDelegate ? Data : View)
|
||||
var items = LoadData.HasDelegate ? Data : View;
|
||||
if (items != null)
|
||||
{
|
||||
RenderItem(builder, item);
|
||||
foreach (var item in items)
|
||||
{
|
||||
RenderItem(builder, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -160,21 +163,18 @@ namespace Radzen
|
||||
//
|
||||
}
|
||||
|
||||
System.Collections.Generic.HashSet<object> keys = new System.Collections.Generic.HashSet<object>();
|
||||
HashSet<object> keys = new HashSet<object>();
|
||||
|
||||
internal object GetKey(object item)
|
||||
internal object? GetKey(object item)
|
||||
{
|
||||
var value = GetItemOrValueFromProperty(item, ValueProperty);
|
||||
var value = GetItemOrValueFromProperty(item, ValueProperty ?? string.Empty);
|
||||
|
||||
if (!keys.Contains(value))
|
||||
if (value != null)
|
||||
{
|
||||
keys.Add(value);
|
||||
return value;
|
||||
}
|
||||
else
|
||||
{
|
||||
return item;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -182,7 +182,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The header template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment HeaderTemplate { get; set; }
|
||||
public RenderFragment? HeaderTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether filtering is allowed. Set to <c>false</c> by default.
|
||||
@@ -231,21 +231,21 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The template.</value>
|
||||
[Parameter]
|
||||
public RenderFragment<dynamic> Template { get; set; }
|
||||
public RenderFragment<dynamic>? Template { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value property.
|
||||
/// </summary>
|
||||
/// <value>The value property.</value>
|
||||
[Parameter]
|
||||
public string ValueProperty { get; set; }
|
||||
public string? ValueProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the disabled property.
|
||||
/// </summary>
|
||||
/// <value>The disabled property.</value>
|
||||
[Parameter]
|
||||
public string DisabledProperty { get; set; }
|
||||
public string? DisabledProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the remove chip button title.
|
||||
@@ -282,7 +282,7 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// The selected item
|
||||
/// </summary>
|
||||
protected object selectedItem = null;
|
||||
protected object? selectedItem;
|
||||
Type GetItemType(IEnumerable items)
|
||||
{
|
||||
var firstType = items.Cast<object>().FirstOrDefault()?.GetType() ?? typeof(object);
|
||||
@@ -301,7 +301,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
protected virtual async System.Threading.Tasks.Task SelectAll()
|
||||
{
|
||||
if (Disabled)
|
||||
if (Disabled || View == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -316,11 +316,14 @@ namespace Radzen
|
||||
selectedItems.Clear();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(ValueProperty))
|
||||
if (!string.IsNullOrEmpty(ValueProperty) && Data != null)
|
||||
{
|
||||
var elementType = PropertyAccess.GetElementType(Data.GetType());
|
||||
System.Reflection.PropertyInfo pi = PropertyAccess.GetProperty(elementType, ValueProperty);
|
||||
internalValue = selectedItems.Select(i => GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
|
||||
System.Reflection.PropertyInfo? pi = PropertyAccess.GetProperty(elementType, ValueProperty);
|
||||
if (pi != null)
|
||||
{
|
||||
internalValue = selectedItems.Select(i => GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -329,25 +332,34 @@ namespace Radzen
|
||||
internalValue = selectedItems.AsQueryable().Cast(type);
|
||||
}
|
||||
|
||||
await collectionAssignment.MakeAssignment((IEnumerable)internalValue, ValueChanged);
|
||||
if (internalValue != null)
|
||||
{
|
||||
await collectionAssignment.MakeAssignment((IEnumerable)internalValue, ValueChanged);
|
||||
}
|
||||
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
|
||||
await Change.InvokeAsync(internalValue);
|
||||
|
||||
StateHasChanged();
|
||||
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", GetId());
|
||||
if (JSRuntime != null)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", GetId());
|
||||
}
|
||||
}
|
||||
|
||||
internal bool IsAllSelected()
|
||||
{
|
||||
List<object> notDisabledItemsInList = View.Cast<object>().ToList()
|
||||
List<object> notDisabledItemsInList = View != null ? View.Cast<object>().ToList()
|
||||
.Where(i => disabledPropertyGetter == null || disabledPropertyGetter(i) as bool? != true)
|
||||
.ToList();
|
||||
.ToList() : new List<object>();
|
||||
|
||||
if (LoadData.HasDelegate && !string.IsNullOrEmpty(ValueProperty))
|
||||
{
|
||||
return View != null && notDisabledItemsInList.Count > 0 && notDisabledItemsInList
|
||||
.All(i => IsItemSelectedByValue(GetItemOrValueFromProperty(i, ValueProperty)));
|
||||
.All(i => {
|
||||
var value = GetItemOrValueFromProperty(i, ValueProperty);
|
||||
return value != null ? IsItemSelectedByValue(value) : false;
|
||||
});
|
||||
}
|
||||
|
||||
return View != null && notDisabledItemsInList.Count > 0 && selectedItems.Count == notDisabledItemsInList.Count;
|
||||
@@ -365,14 +377,17 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// Clears all.
|
||||
/// </summary>
|
||||
protected async System.Threading.Tasks.Task ClearAll()
|
||||
protected async Task ClearAll()
|
||||
{
|
||||
if (Disabled)
|
||||
return;
|
||||
|
||||
searchText = null;
|
||||
await SearchTextChanged.InvokeAsync(searchText);
|
||||
await JSRuntime.InvokeAsync<string>("Radzen.setInputValue", search, "");
|
||||
if (JSRuntime != null)
|
||||
{
|
||||
await JSRuntime.InvokeAsync<string>("Radzen.setInputValue", search, "");
|
||||
}
|
||||
|
||||
internalValue = collectionAssignment.GetCleared();
|
||||
selectedItem = null;
|
||||
@@ -381,7 +396,7 @@ namespace Radzen
|
||||
|
||||
selectedIndex = -1;
|
||||
|
||||
await ValueChanged.InvokeAsync((T)internalValue);
|
||||
await ValueChanged.InvokeAsync(internalValue != null ? (T)internalValue : default(T)!);
|
||||
if (FieldIdentifier.FieldName != null) { EditContext?.NotifyFieldChanged(FieldIdentifier); }
|
||||
await Change.InvokeAsync(internalValue);
|
||||
|
||||
@@ -393,14 +408,14 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// The data
|
||||
/// </summary>
|
||||
IEnumerable _data;
|
||||
IEnumerable? _data;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
[Parameter]
|
||||
public override IEnumerable Data
|
||||
public override IEnumerable? Data
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -466,22 +481,26 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
Func<object, object> GetGetter(string propertyName, Type type)
|
||||
Func<object, object?> GetGetter(string propertyName, Type type)
|
||||
{
|
||||
if (propertyName?.Contains("[") == true)
|
||||
if (propertyName?.Contains('[', StringComparison.Ordinal) == true)
|
||||
{
|
||||
var getter = typeof(PropertyAccess).GetMethod("Getter", [typeof(string), typeof(Type)]);
|
||||
if (getter == null)
|
||||
{
|
||||
return PropertyAccess.Getter<object, object?>(propertyName, type);
|
||||
}
|
||||
var getterMethod = getter.MakeGenericMethod([type, typeof(object)]);
|
||||
|
||||
return (i) => getterMethod.Invoke(i, [propertyName, type]);
|
||||
return (i) => getterMethod.Invoke(i, [propertyName, type])!;
|
||||
}
|
||||
|
||||
return PropertyAccess.Getter<object, object>(propertyName, type);
|
||||
return PropertyAccess.Getter<object, object?>(propertyName ?? string.Empty, type);
|
||||
}
|
||||
|
||||
internal Func<object, object> valuePropertyGetter;
|
||||
internal Func<object, object> textPropertyGetter;
|
||||
internal Func<object, object> disabledPropertyGetter;
|
||||
internal Func<object, object?>? valuePropertyGetter;
|
||||
internal Func<object, object?>? textPropertyGetter;
|
||||
internal Func<object, object?>? disabledPropertyGetter;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the item or value from property.
|
||||
@@ -489,7 +508,7 @@ namespace Radzen
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="property">The property.</param>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object GetItemOrValueFromProperty(object item, string property)
|
||||
public object? GetItemOrValueFromProperty(object? item, string property)
|
||||
{
|
||||
if (item != null)
|
||||
{
|
||||
@@ -610,16 +629,19 @@ namespace Radzen
|
||||
if (Disabled)
|
||||
return;
|
||||
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.togglePopup", Element, PopupID, true);
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", isFilter ? UniqueID : SearchID);
|
||||
if (JSRuntime != null)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.togglePopup", Element, PopupID, true);
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.focusElement", isFilter ? UniqueID : SearchID);
|
||||
}
|
||||
|
||||
if (list != null)
|
||||
if (list != null && JSRuntime != null)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.selectListItem", search, list, selectedIndex);
|
||||
}
|
||||
}
|
||||
|
||||
internal bool preventKeydown = false;
|
||||
internal bool preventKeydown;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the key press.
|
||||
@@ -627,9 +649,9 @@ namespace Radzen
|
||||
/// <param name="args">The <see cref="Microsoft.AspNetCore.Components.Web.KeyboardEventArgs"/> instance containing the event data.</param>
|
||||
/// <param name="isFilter">if set to <c>true</c> [is filter].</param>
|
||||
/// <param name="shouldSelectOnChange">Should select item on item change with keyboard.</param>
|
||||
protected virtual async System.Threading.Tasks.Task HandleKeyPress(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs args, bool isFilter = false, bool? shouldSelectOnChange = null)
|
||||
protected virtual async Task HandleKeyPress(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs args, bool isFilter = false, bool? shouldSelectOnChange = null)
|
||||
{
|
||||
if (Disabled || Data == null)
|
||||
if (Disabled || Data == null || args == null)
|
||||
return;
|
||||
|
||||
List<object> items = Enumerable.Empty<object>().ToList();
|
||||
@@ -649,7 +671,7 @@ namespace Radzen
|
||||
}
|
||||
else
|
||||
{
|
||||
items = View.Cast<object>().ToList();
|
||||
items = View != null ? View.Cast<object>().ToList() : Enumerable.Empty<object>().ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,16 +683,19 @@ namespace Radzen
|
||||
|
||||
try
|
||||
{
|
||||
selectedIndex = await JSRuntime.InvokeAsync<int>("Radzen.focusListItem", search, list, key == "ArrowDown" || key == "ArrowRight", selectedIndex);
|
||||
|
||||
var popupOpened = await JSRuntime.InvokeAsync<bool>("Radzen.popupOpened", PopupID);
|
||||
|
||||
if (!Multiple && !popupOpened && shouldSelectOnChange != false)
|
||||
if (JSRuntime != null)
|
||||
{
|
||||
var itemToSelect = items.ElementAtOrDefault(selectedIndex);
|
||||
if (itemToSelect != null)
|
||||
selectedIndex = await JSRuntime.InvokeAsync<int>("Radzen.focusListItem", search, list, key == "ArrowDown" || key == "ArrowRight", selectedIndex);
|
||||
|
||||
var popupOpened = await JSRuntime.InvokeAsync<bool>("Radzen.popupOpened", PopupID);
|
||||
|
||||
if (!Multiple && !popupOpened && shouldSelectOnChange != false)
|
||||
{
|
||||
await OnSelectItem(itemToSelect, true);
|
||||
var itemToSelect = items.ElementAtOrDefault(selectedIndex);
|
||||
if (itemToSelect != null)
|
||||
{
|
||||
await OnSelectItem(itemToSelect, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -683,37 +708,43 @@ namespace Radzen
|
||||
{
|
||||
preventKeydown = true;
|
||||
|
||||
if (selectedIndex == -1 && items.Count() == 1)
|
||||
if (selectedIndex == -1 && items.Count == 1)
|
||||
{
|
||||
selectedIndex = 0;
|
||||
}
|
||||
|
||||
if (selectedIndex >= 0 && selectedIndex <= items.Count() - 1)
|
||||
if (JSRuntime != null)
|
||||
{
|
||||
var itemToSelect = items.ElementAtOrDefault(selectedIndex);
|
||||
|
||||
await JSRuntime.InvokeAsync<string>("Radzen.setInputValue", search, $"{searchText}".Trim());
|
||||
|
||||
if (itemToSelect != null)
|
||||
if (selectedIndex >= 0 && selectedIndex <= items.Count - 1)
|
||||
{
|
||||
await OnSelectItem(itemToSelect, true);
|
||||
var itemToSelect = items.ElementAtOrDefault(selectedIndex);
|
||||
|
||||
await JSRuntime.InvokeAsync<string>("Radzen.setInputValue", search, $"{searchText}".Trim());
|
||||
|
||||
if (itemToSelect != null)
|
||||
{
|
||||
await OnSelectItem(itemToSelect, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var popupOpened = await JSRuntime.InvokeAsync<bool>("Radzen.popupOpened", PopupID);
|
||||
var popupOpened = await JSRuntime.InvokeAsync<bool>("Radzen.popupOpened", PopupID);
|
||||
|
||||
if (!popupOpened)
|
||||
{
|
||||
if(key != "Space")
|
||||
if (!popupOpened)
|
||||
{
|
||||
await OpenPopup(key, isFilter);
|
||||
if (key != "Space")
|
||||
{
|
||||
await OpenPopup(key, isFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Multiple && (!isFilter || key != "Space"))
|
||||
else
|
||||
{
|
||||
await ClosePopup(key);
|
||||
if (!Multiple && (!isFilter || key != "Space"))
|
||||
{
|
||||
if (!Multiple && !isFilter)
|
||||
{
|
||||
await ClosePopup(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -758,9 +789,20 @@ namespace Radzen
|
||||
else if (args.Key.Length == 1 && !args.CtrlKey && !args.AltKey && !args.ShiftKey)
|
||||
{
|
||||
// searching for element
|
||||
var filteredItems = Query.Where(TextProperty, args.Key, StringFilterOperator.StartsWith, FilterCaseSensitivity.CaseInsensitive)
|
||||
.Cast(Query.ElementType).Cast<dynamic>().ToList();
|
||||
|
||||
if (Query == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var query = Query;
|
||||
var elementType = query.ElementType;
|
||||
if (elementType == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var filteredItems = (!string.IsNullOrEmpty(TextProperty) ?
|
||||
query.Where(TextProperty, args.Key, StringFilterOperator.StartsWith, FilterCaseSensitivity.CaseInsensitive) :
|
||||
query)
|
||||
.Cast(elementType).Cast<dynamic>().ToList();
|
||||
|
||||
if (previousKey != args.Key)
|
||||
{
|
||||
@@ -768,7 +810,7 @@ namespace Radzen
|
||||
itemIndex = -1;
|
||||
}
|
||||
|
||||
itemIndex = itemIndex + 1 >= filteredItems.Count() ? 0 : itemIndex + 1;
|
||||
itemIndex = itemIndex + 1 >= filteredItems.Count ? 0 : itemIndex + 1;
|
||||
var itemToSelect = filteredItems.ElementAtOrDefault(itemIndex);
|
||||
|
||||
if (itemToSelect is not null)
|
||||
@@ -785,7 +827,10 @@ namespace Radzen
|
||||
{
|
||||
selectedIndex = result.Index;
|
||||
}
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.selectListItem", list, list, result.Index);
|
||||
if (JSRuntime != null)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.selectListItem", list, list, result.Index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -795,14 +840,17 @@ namespace Radzen
|
||||
|
||||
internal virtual async Task ClosePopup(string key)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
if (JSRuntime != null)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.closePopup", PopupID);
|
||||
}
|
||||
}
|
||||
|
||||
int itemIndex;
|
||||
string previousKey;
|
||||
string? previousKey;
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:FilterKeyPress" /> event.
|
||||
/// Handles the FilterKeyPress event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="Microsoft.AspNetCore.Components.Web.KeyboardEventArgs"/> instance containing the event data.</param>
|
||||
protected virtual async System.Threading.Tasks.Task OnFilterKeyPress(Microsoft.AspNetCore.Components.Web.KeyboardEventArgs args)
|
||||
@@ -852,13 +900,15 @@ namespace Radzen
|
||||
|
||||
if (Multiple)
|
||||
selectedIndex = -1;
|
||||
|
||||
await JSRuntime.InvokeAsync<string>("Radzen.repositionPopup", Element, PopupID);
|
||||
if (JSRuntime != null)
|
||||
{
|
||||
await JSRuntime.InvokeAsync<string>("Radzen.repositionPopup", Element, PopupID);
|
||||
}
|
||||
await InvokeAsync(() => SearchTextChanged.InvokeAsync(SearchText));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:KeyPress" /> event.
|
||||
/// Handles the KeyPress event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="Microsoft.AspNetCore.Components.Web.KeyboardEventArgs"/> instance containing the event data.</param>
|
||||
/// <param name="shouldSelectOnChange">Should select item on item change with keyboard.</param>
|
||||
@@ -872,13 +922,13 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="isFromKey">if set to <c>true</c> [is from key].</param>
|
||||
protected virtual async System.Threading.Tasks.Task OnSelectItem(object item, bool isFromKey = false)
|
||||
protected virtual async System.Threading.Tasks.Task OnSelectItem(object? item, bool isFromKey = false)
|
||||
{
|
||||
await SelectItem(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:Filter" /> event.
|
||||
/// Handles the Filter event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="ChangeEventArgs"/> instance containing the event data.</param>
|
||||
protected virtual async System.Threading.Tasks.Task OnFilter(ChangeEventArgs args)
|
||||
@@ -946,7 +996,7 @@ namespace Radzen
|
||||
if (valueChanged)
|
||||
{
|
||||
internalValue = parameters.GetValueOrDefault<object>(nameof(Value));
|
||||
if (PreserveCollectionOnSelection)
|
||||
if (PreserveCollectionOnSelection && internalValue != null)
|
||||
{
|
||||
collectionAssignment = new ReferenceGenericCollectionAssignment((T)internalValue);
|
||||
}
|
||||
@@ -969,7 +1019,7 @@ namespace Radzen
|
||||
}
|
||||
|
||||
var shouldClose = visibleChanged && !Visible;
|
||||
if (shouldClose && !firstRender)
|
||||
if (shouldClose && !firstRender && JSRuntime != null)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.destroyPopup", PopupID);
|
||||
}
|
||||
@@ -991,18 +1041,24 @@ namespace Radzen
|
||||
}
|
||||
}
|
||||
|
||||
SelectItemFromValue(internalValue);
|
||||
if (internalValue != null)
|
||||
{
|
||||
SelectItemFromValue(internalValue);
|
||||
}
|
||||
|
||||
return base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:Change" /> event.
|
||||
/// Handles the Change event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="ChangeEventArgs"/> instance containing the event data.</param>
|
||||
protected void OnChange(ChangeEventArgs args)
|
||||
{
|
||||
internalValue = args.Value;
|
||||
if (args != null)
|
||||
{
|
||||
internalValue = args.Value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1014,7 +1070,8 @@ namespace Radzen
|
||||
{
|
||||
if (!string.IsNullOrEmpty(ValueProperty))
|
||||
{
|
||||
return IsItemSelectedByValue(GetItemOrValueFromProperty(item, ValueProperty));
|
||||
var value = GetItemOrValueFromProperty(item, ValueProperty);
|
||||
return value != null ? IsItemSelectedByValue(value) : false;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1034,7 +1091,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The selected item.</value>
|
||||
[Parameter]
|
||||
public object SelectedItem
|
||||
public object? SelectedItem
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -1072,13 +1129,13 @@ namespace Radzen
|
||||
/// Gets the view.
|
||||
/// </summary>
|
||||
/// <value>The view.</value>
|
||||
protected override IEnumerable View
|
||||
protected override IEnumerable? View
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_view == null && Query != null)
|
||||
{
|
||||
_view = Query.Where(TextProperty, searchText, FilterOperator, FilterCaseSensitivity);
|
||||
_view = Query.Where(TextProperty ?? string.Empty, searchText, FilterOperator, FilterCaseSensitivity);
|
||||
}
|
||||
|
||||
return _view;
|
||||
@@ -1090,7 +1147,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
void SetSelectedIndexFromSelectedItem()
|
||||
{
|
||||
if (selectedItem != null)
|
||||
if (selectedItem != null && View != null)
|
||||
{
|
||||
if (typeof(EnumerableQuery).IsAssignableFrom(View.GetType()))
|
||||
{
|
||||
@@ -1112,17 +1169,17 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="raiseChange">if set to <c>true</c> [raise change].</param>
|
||||
internal async System.Threading.Tasks.Task SelectItemInternal(object item, bool raiseChange = true)
|
||||
internal async Task SelectItemInternal(object item, bool raiseChange = true)
|
||||
{
|
||||
await SelectItem(item, raiseChange);
|
||||
}
|
||||
|
||||
internal object internalValue;
|
||||
internal object? internalValue;
|
||||
|
||||
/// <summary>
|
||||
/// Will add/remove selected items from a bound ICollection<T>, instead of replacing it.
|
||||
/// </summary>
|
||||
protected bool PreserveCollectionOnSelection = false;
|
||||
protected bool PreserveCollectionOnSelection;
|
||||
private DefaultCollectionAssignment collectionAssignment = new();
|
||||
|
||||
/// <summary>
|
||||
@@ -1130,7 +1187,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <param name="item">The item.</param>
|
||||
/// <param name="raiseChange">if set to <c>true</c> [raise change].</param>
|
||||
public async System.Threading.Tasks.Task SelectItem(object item, bool raiseChange = true)
|
||||
public async Task SelectItem(object? item, bool raiseChange = true)
|
||||
{
|
||||
if (disabledPropertyGetter != null && item != null && disabledPropertyGetter(item) as bool? == true)
|
||||
{
|
||||
@@ -1143,7 +1200,7 @@ namespace Radzen
|
||||
return;
|
||||
|
||||
selectedItem = item;
|
||||
if (!string.IsNullOrEmpty(ValueProperty))
|
||||
if (!string.IsNullOrEmpty(ValueProperty) && item != null)
|
||||
{
|
||||
internalValue = PropertyAccess.GetItemOrValueFromProperty(item, ValueProperty);
|
||||
}
|
||||
@@ -1158,16 +1215,26 @@ namespace Radzen
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateSelectedItems(item);
|
||||
if (item != null)
|
||||
{
|
||||
UpdateSelectedItems(item);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(ValueProperty))
|
||||
if (!string.IsNullOrEmpty(ValueProperty) && Data != null)
|
||||
{
|
||||
var elementType = PropertyAccess.GetElementType(Data.GetType());
|
||||
System.Reflection.PropertyInfo pi = PropertyAccess.GetProperty(elementType, ValueProperty);
|
||||
internalValue = selectedItems.Select(i => GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
|
||||
System.Reflection.PropertyInfo? pi = PropertyAccess.GetProperty(elementType, ValueProperty);
|
||||
if(pi != null)
|
||||
{
|
||||
internalValue = selectedItems.Select(i => GetItemOrValueFromProperty(i, ValueProperty)).AsQueryable().Cast(pi.PropertyType);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (Data == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var query = Data.AsQueryable();
|
||||
var elementType = query.ElementType;
|
||||
|
||||
@@ -1196,11 +1263,14 @@ namespace Radzen
|
||||
{
|
||||
if (Multiple)
|
||||
{
|
||||
await collectionAssignment.MakeAssignment((IEnumerable)internalValue, ValueChanged);
|
||||
if (internalValue != null)
|
||||
{
|
||||
await collectionAssignment.MakeAssignment((IEnumerable)internalValue, ValueChanged);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await ValueChanged.InvokeAsync(internalValue != null ? (T)internalValue : default);
|
||||
await ValueChanged.InvokeAsync(internalValue != null ? (T)internalValue : default(T)!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1212,7 +1282,7 @@ namespace Radzen
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override object GetValue()
|
||||
public override object? GetValue()
|
||||
{
|
||||
return internalValue;
|
||||
}
|
||||
@@ -1223,7 +1293,7 @@ namespace Radzen
|
||||
{
|
||||
var value = GetItemOrValueFromProperty(item, ValueProperty);
|
||||
|
||||
if (!IsItemSelectedByValue(value))
|
||||
if (value != null && !IsItemSelectedByValue(value))
|
||||
{
|
||||
selectedItems.Add(item);
|
||||
}
|
||||
@@ -1292,7 +1362,7 @@ namespace Radzen
|
||||
|
||||
if (typeof(EnumerableQuery).IsAssignableFrom(view.GetType()))
|
||||
{
|
||||
item = view.OfType<object>().Where(i => object.Equals(GetItemOrValueFromProperty(i, ValueProperty), v)).FirstOrDefault();
|
||||
item = view.OfType<object>().Where(i => object.Equals(GetItemOrValueFromProperty(i, ValueProperty), v)).FirstOrDefault()!;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1305,7 +1375,7 @@ namespace Radzen
|
||||
}
|
||||
},
|
||||
LogicalFilterOperator.And,
|
||||
FilterCaseSensitivity.Default).FirstOrDefault();
|
||||
FilterCaseSensitivity.Default).FirstOrDefault()!;
|
||||
}
|
||||
|
||||
if (!object.Equals(item, null) && !selectedItems.AsQueryable().Where(i => object.Equals(GetItemOrValueFromProperty(i, ValueProperty), v)).Any())
|
||||
@@ -1330,7 +1400,7 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// For lists of objects, an IEqualityComparer to control how selected items are determined
|
||||
/// </summary>
|
||||
[Parameter] public IEqualityComparer<object> ItemComparer { get; set; }
|
||||
[Parameter] public IEqualityComparer<object>? ItemComparer { get; set; }
|
||||
|
||||
internal bool IsItemSelectedByValue(object v)
|
||||
{
|
||||
@@ -1353,6 +1423,8 @@ namespace Radzen
|
||||
base.Dispose();
|
||||
|
||||
keys.Clear();
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private class DefaultCollectionAssignment
|
||||
@@ -1363,42 +1435,55 @@ namespace Radzen
|
||||
{
|
||||
if (object.Equals(selectedItems, null))
|
||||
{
|
||||
await valueChanged.InvokeAsync(default(T));
|
||||
await valueChanged.InvokeAsync(default(T)!);
|
||||
}
|
||||
else
|
||||
{
|
||||
var list = (IList)Activator.CreateInstance(typeof(T));
|
||||
foreach (var i in (IEnumerable)selectedItems)
|
||||
var list = (IList?)Activator.CreateInstance<T>();
|
||||
if (list != null)
|
||||
{
|
||||
list.Add(i);
|
||||
foreach (var i in (IEnumerable)selectedItems)
|
||||
{
|
||||
list.Add(i);
|
||||
}
|
||||
await valueChanged.InvokeAsync((T)(object)list);
|
||||
}
|
||||
else
|
||||
{
|
||||
await valueChanged.InvokeAsync(default(T)!);
|
||||
}
|
||||
await valueChanged.InvokeAsync((T)(object)list);
|
||||
}
|
||||
}
|
||||
else if (typeof(T).IsGenericType && typeof(ICollection<>).MakeGenericType(typeof(T).GetGenericArguments()[0]).IsAssignableFrom(typeof(T)))
|
||||
{
|
||||
if (object.Equals(selectedItems, null))
|
||||
{
|
||||
await valueChanged.InvokeAsync(default(T));
|
||||
await valueChanged.InvokeAsync(default(T)!);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(typeof(T).GetGenericArguments()[0]));
|
||||
var list = (IList?)Activator.CreateInstance(typeof(List<>).MakeGenericType(typeof(T).GetGenericArguments()[0]));
|
||||
if (list != null)
|
||||
{
|
||||
foreach (var i in (IEnumerable)selectedItems)
|
||||
{
|
||||
list.Add(i);
|
||||
}
|
||||
await valueChanged.InvokeAsync((T)(object)list);
|
||||
}
|
||||
else
|
||||
{
|
||||
await valueChanged.InvokeAsync(default(T)!);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await valueChanged.InvokeAsync(object.Equals(selectedItems, null) ? default(T) : (T)selectedItems);
|
||||
await valueChanged.InvokeAsync(object.Equals(selectedItems, null) ? default(T)! : (T)selectedItems);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual T GetCleared()
|
||||
public virtual T? GetCleared()
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
@@ -1408,9 +1493,9 @@ namespace Radzen
|
||||
{
|
||||
private readonly T originalCollection;
|
||||
private readonly bool canHandle;
|
||||
private readonly System.Reflection.MethodInfo clearMethod;
|
||||
private readonly System.Reflection.MethodInfo addMethod;
|
||||
private readonly System.Reflection.MethodInfo removeMethod;
|
||||
private readonly System.Reflection.MethodInfo? clearMethod;
|
||||
private readonly System.Reflection.MethodInfo? addMethod;
|
||||
private readonly System.Reflection.MethodInfo? removeMethod;
|
||||
|
||||
public ReferenceGenericCollectionAssignment(T originalCollection)
|
||||
{
|
||||
@@ -1437,34 +1522,34 @@ namespace Radzen
|
||||
|
||||
public override async Task MakeAssignment(IEnumerable selectedItems, EventCallback<T> valueChanged)
|
||||
{
|
||||
if (!canHandle)
|
||||
if (!canHandle || originalCollection == null)
|
||||
{
|
||||
// Fallback to default behavior when we can't handle the type
|
||||
// Fallback to default behavior when we can't handle the type or originalCollection is null
|
||||
await base.MakeAssignment(selectedItems, valueChanged);
|
||||
return;
|
||||
}
|
||||
|
||||
var currentItems = selectedItems.Cast<object>().ToHashSet();
|
||||
var existingItems = ((IEnumerable)originalCollection).Cast<object>().ToHashSet();
|
||||
var existingItems = (originalCollection as IEnumerable)?.Cast<object>().ToHashSet() ?? new HashSet<object>();
|
||||
foreach (var i in currentItems)
|
||||
{
|
||||
if (!existingItems.Contains(i))
|
||||
addMethod.Invoke(originalCollection, [i]);
|
||||
addMethod!.Invoke(originalCollection, [i]);
|
||||
}
|
||||
foreach (var i in existingItems)
|
||||
{
|
||||
if (!currentItems.Contains(i))
|
||||
removeMethod.Invoke(originalCollection, [i]);
|
||||
removeMethod!.Invoke(originalCollection, [i]);
|
||||
}
|
||||
|
||||
await valueChanged.InvokeAsync(originalCollection);
|
||||
}
|
||||
|
||||
public override T GetCleared()
|
||||
public override T? GetCleared()
|
||||
{
|
||||
if (canHandle)
|
||||
if (canHandle && originalCollection != null)
|
||||
{
|
||||
clearMethod.Invoke(originalCollection, null);
|
||||
clearMethod!.Invoke(originalCollection, null);
|
||||
return originalCollection;
|
||||
}
|
||||
return base.GetCleared();
|
||||
|
||||
@@ -10,7 +10,7 @@ public class DropDownBaseItemRenderEventArgs<TValue>
|
||||
/// <summary>
|
||||
/// Gets the data item.
|
||||
/// </summary>
|
||||
public object Item { get; internal set; }
|
||||
public object? Item { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this item is visible.
|
||||
|
||||
@@ -10,6 +10,6 @@ public class DropDownItemRenderEventArgs<TValue> : DropDownBaseItemRenderEventAr
|
||||
/// <summary>
|
||||
/// Gets the DropDown.
|
||||
/// </summary>
|
||||
public RadzenDropDown<TValue> DropDown { get; internal set; }
|
||||
public RadzenDropDown<TValue>? DropDown { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,13 @@ namespace System.Linq.Dynamic.Core
|
||||
/// </summary>
|
||||
public static class DynamicExtensions
|
||||
{
|
||||
static readonly Func<string, Type> typeLocator = type => AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(a => a.GetTypes()).FirstOrDefault(t => t.FullName.Replace("+", ".") == type);
|
||||
static readonly Func<string, Type?> typeLocator = type => AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(a => a.GetTypes())
|
||||
.FirstOrDefault(t =>
|
||||
{
|
||||
var fullName = t.FullName;
|
||||
return fullName != null && fullName.Replace("+", ".", StringComparison.Ordinal) == type;
|
||||
});
|
||||
|
||||
/// <summary>
|
||||
/// Filters using the specified filter descriptors.
|
||||
@@ -18,28 +23,30 @@ namespace System.Linq.Dynamic.Core
|
||||
public static IQueryable<T> Where<T>(
|
||||
this IQueryable<T> source,
|
||||
string predicate,
|
||||
object[] parameters = null, object[] otherParameters = null)
|
||||
object[]? parameters = null, object[]? otherParameters = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
|
||||
try
|
||||
{
|
||||
if (parameters != null && !string.IsNullOrEmpty(predicate))
|
||||
{
|
||||
predicate = Regex.Replace(predicate, @"@(\d+)", match =>
|
||||
{
|
||||
int index = int.Parse(match.Groups[1].Value);
|
||||
int index = int.Parse(match.Groups[1].Value, System.Globalization.CultureInfo.InvariantCulture);
|
||||
if (index >= parameters.Length)
|
||||
throw new InvalidOperationException($"No parameter provided for {match.Value}");
|
||||
|
||||
return ExpressionSerializer.FormatValue(parameters[index]);
|
||||
return ExpressionSerializer.FormatValue(parameters[index]) ?? string.Empty;
|
||||
});
|
||||
}
|
||||
|
||||
predicate = (predicate == "true" ? "" : predicate)
|
||||
.Replace("DateTime(", "DateTime.Parse(")
|
||||
.Replace("DateTimeOffset(", "DateTimeOffset.Parse(")
|
||||
.Replace("DateOnly(", "DateOnly.Parse(")
|
||||
.Replace("Guid(", "Guid.Parse(")
|
||||
.Replace(" = ", " == ");
|
||||
predicate = (predicate == "true" ? "" : predicate ?? string.Empty)
|
||||
.Replace("DateTime(", "DateTime.Parse(", StringComparison.Ordinal)
|
||||
.Replace("DateTimeOffset(", "DateTimeOffset.Parse(", StringComparison.Ordinal)
|
||||
.Replace("DateOnly(", "DateOnly.Parse(", StringComparison.Ordinal)
|
||||
.Replace("Guid(", "Guid.Parse(", StringComparison.Ordinal)
|
||||
.Replace(" = ", " == ", StringComparison.Ordinal);
|
||||
|
||||
return !string.IsNullOrEmpty(predicate) ?
|
||||
source.Where(ExpressionParser.ParsePredicate<T>(predicate, typeLocator)) : source;
|
||||
@@ -56,8 +63,10 @@ namespace System.Linq.Dynamic.Core
|
||||
public static IOrderedQueryable<T> OrderBy<T>(
|
||||
this IQueryable<T> source,
|
||||
string selector,
|
||||
object[] parameters = null)
|
||||
object[]? parameters = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
|
||||
try
|
||||
{
|
||||
return QueryableExtension.OrderBy(source, selector);
|
||||
@@ -71,8 +80,10 @@ namespace System.Linq.Dynamic.Core
|
||||
/// <summary>
|
||||
/// Projects each element of a sequence into a collection of property values.
|
||||
/// </summary>
|
||||
public static IQueryable Select<T>(this IQueryable<T> source, string selector, object[] parameters = null)
|
||||
public static IQueryable Select<T>(this IQueryable<T> source, string selector, object[]? parameters = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
|
||||
if (source.ElementType == typeof(object))
|
||||
{
|
||||
var elementType = source.ElementType;
|
||||
@@ -95,8 +106,10 @@ namespace System.Linq.Dynamic.Core
|
||||
/// <summary>
|
||||
/// Projects each element of a sequence into a collection of property values.
|
||||
/// </summary>
|
||||
public static IQueryable Select(this IQueryable source, string selector, object[] parameters = null)
|
||||
public static IQueryable Select(this IQueryable source, string selector, object[]? parameters = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
ArgumentNullException.ThrowIfNull(selector);
|
||||
return source.Select(selector, expression => ExpressionParser.ParseLambda(expression, source.ElementType));
|
||||
}
|
||||
|
||||
@@ -109,18 +122,27 @@ namespace System.Linq.Dynamic.Core
|
||||
return source;
|
||||
}
|
||||
|
||||
if (!selector.Contains("=>"))
|
||||
if (!selector.Contains("=>", StringComparison.Ordinal))
|
||||
{
|
||||
var properties = selector
|
||||
.Replace("new (", "").Replace(")", "").Replace("new {", "").Replace("}", "").Trim()
|
||||
.Replace("new (", "", StringComparison.Ordinal).Replace(")", "", StringComparison.Ordinal).Replace("new {", "", StringComparison.Ordinal).Replace("}", "", StringComparison.Ordinal).Trim()
|
||||
.Split(",", StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
selector = string.Join(", ", properties
|
||||
.Select(s => (s.Contains(" as ") ? s.Split(" as ").LastOrDefault().Trim().Replace(".", "_") : s.Trim().Replace(".", "_")) +
|
||||
" = " + $"it.{s.Split(" as ").FirstOrDefault().Replace(".", "?.").Trim()}"));
|
||||
.Select(s =>
|
||||
{
|
||||
var parts = s.Split(" as ", StringSplitOptions.RemoveEmptyEntries);
|
||||
var sourcePart = (parts.FirstOrDefault() ?? s).Trim();
|
||||
var targetPart = (parts.Length > 1 ? parts.Last() : sourcePart).Trim();
|
||||
|
||||
var safeTarget = targetPart.Replace(".", "_", StringComparison.Ordinal);
|
||||
var safeSource = sourcePart.Replace(".", "?.", StringComparison.Ordinal);
|
||||
|
||||
return $"{safeTarget} = it.{safeSource}";
|
||||
}));
|
||||
}
|
||||
|
||||
var lambda = lambdaCreator(selector.Contains("=>") ? selector : $"it => new {{ {selector} }}");
|
||||
var lambda = lambdaCreator(selector.Contains("=>", StringComparison.Ordinal) ? selector : $"it => new {{ {selector} }}");
|
||||
|
||||
return source.Provider.CreateQuery(Expression.Call(typeof(Queryable), nameof(Queryable.Select),
|
||||
[source.ElementType, lambda.Body.Type], source.Expression, Expression.Quote(lambda)));
|
||||
|
||||
@@ -39,7 +39,7 @@ static class DynamicTypeFactory
|
||||
"set_" + propertyNames[i],
|
||||
MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig,
|
||||
null,
|
||||
[propertyTypes[i]]);
|
||||
new[] { propertyTypes[i] });
|
||||
|
||||
var setterIl = setterMethod.GetILGenerator();
|
||||
setterIl.Emit(OpCodes.Ldarg_0);
|
||||
@@ -51,6 +51,10 @@ static class DynamicTypeFactory
|
||||
}
|
||||
|
||||
var dynamicType = typeBuilder.CreateType();
|
||||
if (dynamicType == null)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to create dynamic type.");
|
||||
}
|
||||
return dynamicType;
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ public class ExpressionParser
|
||||
/// </summary>
|
||||
public static Expression<Func<T, TResult>> ParseLambda<T, TResult>(string expression, Func<string, Type?>? typeResolver = null)
|
||||
{
|
||||
var lambda = ParseLambda(expression, typeof(T), typeResolver);
|
||||
var lambda = ParseLambda<T>(expression, typeResolver);
|
||||
|
||||
return Expression.Lambda<Func<T, TResult>>(lambda.Body, lambda.Parameters[0]);
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public class ExpressionParser
|
||||
}
|
||||
|
||||
private readonly List<Token> tokens;
|
||||
private int position = 0;
|
||||
private int position;
|
||||
private readonly Func<string, Type?>? typeResolver;
|
||||
private readonly Stack<ParameterExpression> parameterStack = new();
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
/// <inheritdoc/>
|
||||
protected override Expression VisitLambda<T>(Expression<T> node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
if (node.Parameters.Count > 1)
|
||||
{
|
||||
_sb.Append("(");
|
||||
@@ -52,6 +53,7 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
/// <inheritdoc/>
|
||||
protected override Expression VisitParameter(ParameterExpression node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
_sb.Append(node.Name);
|
||||
return node;
|
||||
}
|
||||
@@ -59,10 +61,11 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
/// <inheritdoc/>
|
||||
protected override Expression VisitMember(MemberExpression node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
if (node.Expression != null)
|
||||
{
|
||||
Visit(node.Expression);
|
||||
_sb.Append($".{node.Member.Name}");
|
||||
_sb.Append(CultureInfo.InvariantCulture, $".{node.Member.Name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -74,12 +77,13 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
/// <inheritdoc/>
|
||||
protected override Expression VisitMethodCall(MethodCallExpression node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
if (node.Method.IsStatic && node.Arguments.Count > 0 &&
|
||||
(node.Method.DeclaringType == typeof(Enumerable) ||
|
||||
node.Method.DeclaringType == typeof(Queryable)))
|
||||
{
|
||||
Visit(node.Arguments[0]);
|
||||
_sb.Append($".{node.Method.Name}(");
|
||||
_sb.Append(CultureInfo.InvariantCulture, $".{node.Method.Name}(");
|
||||
|
||||
for (int i = 1; i < node.Arguments.Count; i++)
|
||||
{
|
||||
@@ -99,7 +103,7 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
}
|
||||
else if (node.Method.IsStatic)
|
||||
{
|
||||
_sb.Append($"{node.Method.DeclaringType.Name}.{node.Method.Name}(");
|
||||
_sb.Append(CultureInfo.InvariantCulture, $"{node.Method.DeclaringType?.Name}.{node.Method.Name}(");
|
||||
|
||||
for (int i = 0; i < node.Arguments.Count; i++)
|
||||
{
|
||||
@@ -114,11 +118,11 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
if (node.Object != null)
|
||||
{
|
||||
Visit(node.Object);
|
||||
_sb.Append($".{node.Method.Name}(");
|
||||
_sb.Append(CultureInfo.InvariantCulture, $".{node.Method.Name}(");
|
||||
}
|
||||
else
|
||||
{
|
||||
_sb.Append($"{node.Method.Name}(");
|
||||
_sb.Append(CultureInfo.InvariantCulture, $"{node.Method.Name}(");
|
||||
}
|
||||
|
||||
for (int i = 0; i < node.Arguments.Count; i++)
|
||||
@@ -136,6 +140,7 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
/// <inheritdoc/>
|
||||
protected override Expression VisitUnary(UnaryExpression node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
if (node.NodeType == ExpressionType.Not)
|
||||
{
|
||||
_sb.Append("(!(");
|
||||
@@ -146,7 +151,7 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
{
|
||||
if (node.Operand is IndexExpression indexExpr)
|
||||
{
|
||||
_sb.Append($"({node.Type.DisplayName(true).Replace("+",".")})");
|
||||
_sb.Append(CultureInfo.InvariantCulture, $"({node.Type.DisplayName(true).Replace("+", ".", StringComparison.Ordinal)})");
|
||||
|
||||
Visit(indexExpr.Object);
|
||||
|
||||
@@ -175,20 +180,18 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
/// <inheritdoc/>
|
||||
protected override Expression VisitConstant(ConstantExpression node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
_sb.Append(FormatValue(node.Value));
|
||||
return node;
|
||||
}
|
||||
|
||||
internal static string FormatValue(object value)
|
||||
internal static string? FormatValue(object? value)
|
||||
{
|
||||
if (value == null)
|
||||
return "null";
|
||||
|
||||
return value switch
|
||||
{
|
||||
string s when s == string.Empty => @"""""",
|
||||
string s when s.Length == 0 => @"""""",
|
||||
null => "null",
|
||||
string s => @$"""{s.Replace("\"", "\\\"")}""",
|
||||
string s => @$"""{s.Replace("\"", "\\\"", StringComparison.Ordinal)}""",
|
||||
char c => $"'{c}'",
|
||||
bool b => b.ToString().ToLowerInvariant(),
|
||||
DateTime dt => FormatDateTime(dt),
|
||||
@@ -198,7 +201,7 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
Guid guid => $"Guid.Parse(\"{guid.ToString("D", CultureInfo.InvariantCulture)}\")",
|
||||
IEnumerable enumerable when value is not string => FormatEnumerable(enumerable),
|
||||
_ => value.GetType().IsEnum
|
||||
? $"({value.GetType().FullName.Replace("+", ".")})" + Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture).ToString()
|
||||
? $"({value.GetType()?.FullName?.Replace("+", ".", StringComparison.Ordinal)})" + Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType()), CultureInfo.InvariantCulture).ToString()
|
||||
: Convert.ToString(value, CultureInfo.InvariantCulture)
|
||||
};
|
||||
}
|
||||
@@ -216,12 +219,13 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
var arrayType = enumerable.AsQueryable().ElementType;
|
||||
|
||||
var items = enumerable.Cast<object>().Select(FormatValue);
|
||||
return $"new {(Nullable.GetUnderlyingType(arrayType) != null ? arrayType.DisplayName(true).Replace("+", ".") : "")}[] {{ {string.Join(", ", items)} }}";
|
||||
return $"new {(Nullable.GetUnderlyingType(arrayType) != null ? arrayType.DisplayName(true).Replace("+", ".", StringComparison.Ordinal) : "")}[] {{ {string.Join(", ", items)} }}";
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Expression VisitNewArray(NewArrayExpression node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
bool needsParentheses = node.NodeType == ExpressionType.NewArrayInit &&
|
||||
(node.Expressions.Count > 1 || node.Expressions[0].NodeType != ExpressionType.Constant);
|
||||
|
||||
@@ -245,9 +249,10 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
/// <inheritdoc/>
|
||||
protected override Expression VisitBinary(BinaryExpression node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
_sb.Append("(");
|
||||
Visit(node.Left);
|
||||
_sb.Append($" {GetOperator(node.NodeType)} ");
|
||||
_sb.Append(CultureInfo.InvariantCulture, $" {GetOperator(node.NodeType)} ");
|
||||
Visit(node.Right);
|
||||
_sb.Append(")");
|
||||
return node;
|
||||
@@ -256,6 +261,7 @@ public class ExpressionSerializer : ExpressionVisitor
|
||||
/// <inheritdoc/>
|
||||
protected override Expression VisitConditional(ConditionalExpression node)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(node);
|
||||
_sb.Append("(");
|
||||
Visit(node.Test);
|
||||
_sb.Append(" ? ");
|
||||
@@ -333,6 +339,7 @@ public static class SharedTypeExtensions
|
||||
/// <returns>A string representing the type name.</returns>
|
||||
public static string DisplayName(this Type type, bool fullName = true, bool compilable = false)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(type);
|
||||
var stringBuilder = new StringBuilder();
|
||||
ProcessType(stringBuilder, type, fullName, compilable);
|
||||
return stringBuilder.ToString();
|
||||
@@ -443,7 +450,7 @@ public static class SharedTypeExtensions
|
||||
}
|
||||
}
|
||||
|
||||
var genericPartIndex = type.Name.IndexOf('`');
|
||||
var genericPartIndex = type.Name.IndexOf('`', StringComparison.Ordinal);
|
||||
if (genericPartIndex <= 0)
|
||||
{
|
||||
builder.Append(type.Name);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
@@ -18,8 +19,9 @@ namespace Radzen.Blazor
|
||||
/// <summary>
|
||||
/// Gets enum description.
|
||||
/// </summary>
|
||||
public static string GetDisplayDescription(this Enum enumValue, Func<string, string> translationFunction = null)
|
||||
public static string GetDisplayDescription(this Enum enumValue, Func<string, string>? translationFunction = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(enumValue);
|
||||
var enumValueAsString = enumValue.ToString();
|
||||
var val = enumValue.GetType().GetMember(enumValueAsString).FirstOrDefault();
|
||||
var enumVal = val?.GetCustomAttribute<DisplayAttribute>()?.GetDescription() ?? enumValueAsString;
|
||||
@@ -33,10 +35,12 @@ namespace Radzen.Blazor
|
||||
/// <summary>
|
||||
/// Converts Enum to IEnumerable of Value/Text.
|
||||
/// </summary>
|
||||
public static IEnumerable<object> EnumAsKeyValuePair(Type enumType, Func<string, string> translationFunction = null)
|
||||
public static IEnumerable<object> EnumAsKeyValuePair(Type enumType, Func<string, string>? translationFunction = null)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(enumType);
|
||||
|
||||
Type underlyingType = Enum.GetUnderlyingType(enumType);
|
||||
return Enum.GetValues(enumType).Cast<Enum>().Distinct().Select(val => new { Value = Convert.ChangeType(val, underlyingType), Text = val.GetDisplayDescription(translationFunction) });
|
||||
return Enum.GetValues(enumType).Cast<Enum>().Distinct().Select(val => new { Value = Convert.ChangeType(val, underlyingType, CultureInfo.InvariantCulture), Text = val.GetDisplayDescription(translationFunction) });
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -67,7 +71,7 @@ namespace Radzen.Blazor
|
||||
var value = typeValue.ToString();
|
||||
value = Regex.Replace(value, "([^A-Z])([A-Z])", "$1-$2");
|
||||
return Regex.Replace(value, "([A-Z]+)([A-Z][^A-Z$])", "$1-$2")
|
||||
.Trim().ToLower();
|
||||
.Trim().ToLowerInvariant();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public class FileInfo : IBrowserFile
|
||||
//
|
||||
}
|
||||
|
||||
private IBrowserFile source;
|
||||
private IBrowserFile? source;
|
||||
|
||||
/// <summary>
|
||||
/// Creates FileInfo with IBrowserFile as source.
|
||||
@@ -28,7 +28,9 @@ public class FileInfo : IBrowserFile
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
private string name;
|
||||
private string? name;
|
||||
private DateTimeOffset? lastModified;
|
||||
private string? contentType;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the selected file.
|
||||
@@ -37,7 +39,7 @@ public class FileInfo : IBrowserFile
|
||||
{
|
||||
get
|
||||
{
|
||||
return name ?? source.Name;
|
||||
return name ?? source?.Name ?? string.Empty;
|
||||
}
|
||||
set
|
||||
{
|
||||
@@ -65,17 +67,25 @@ public class FileInfo : IBrowserFile
|
||||
/// <summary>
|
||||
/// Gets the IBrowserFile source.
|
||||
/// </summary>
|
||||
public IBrowserFile Source => source;
|
||||
public IBrowserFile? Source => source;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the LastModified.
|
||||
/// </summary>
|
||||
public DateTimeOffset LastModified => source.LastModified;
|
||||
public DateTimeOffset LastModified
|
||||
{
|
||||
get => lastModified ?? source?.LastModified ?? default;
|
||||
set => lastModified = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ContentType.
|
||||
/// </summary>
|
||||
public string ContentType => source.ContentType;
|
||||
public string ContentType
|
||||
{
|
||||
get => contentType ?? source?.ContentType ?? string.Empty;
|
||||
set => contentType = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Open read stream.
|
||||
@@ -85,6 +95,11 @@ public class FileInfo : IBrowserFile
|
||||
/// <returns>The stream.</returns>
|
||||
public System.IO.Stream OpenReadStream(long maxAllowedSize = 512000, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (source == null)
|
||||
{
|
||||
throw new InvalidOperationException("No underlying browser file is associated with this FileInfo instance.");
|
||||
}
|
||||
|
||||
return source.OpenReadStream(maxAllowedSize, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,26 +12,26 @@ public class FilterDescriptor
|
||||
/// Gets or sets the name of the filtered property.
|
||||
/// </summary>
|
||||
/// <value>The property.</value>
|
||||
public string Property { get; set; }
|
||||
public string? Property { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the property type.
|
||||
/// </summary>
|
||||
/// <value>The property type.</value>
|
||||
[JsonIgnore]
|
||||
public Type Type { get; set; }
|
||||
public Type? Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the filtered property.
|
||||
/// </summary>
|
||||
/// <value>The property.</value>
|
||||
public string FilterProperty { get; set; }
|
||||
public string? FilterProperty { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value to filter by.
|
||||
/// </summary>
|
||||
/// <value>The filter value.</value>
|
||||
public object FilterValue { get; set; }
|
||||
public object? FilterValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the operator which will compare the property value with <see cref="FilterValue" />.
|
||||
@@ -43,7 +43,7 @@ public class FilterDescriptor
|
||||
/// Gets or sets a second value to filter by.
|
||||
/// </summary>
|
||||
/// <value>The second filter value.</value>
|
||||
public object SecondFilterValue { get; set; }
|
||||
public object? SecondFilterValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the operator which will compare the property value with <see cref="SecondFilterValue" />.
|
||||
|
||||
@@ -39,8 +39,30 @@ namespace Radzen
|
||||
/// AutoCompleteType.</value>
|
||||
public virtual string AutoCompleteAttribute
|
||||
{
|
||||
get => Attributes != null && Attributes.ContainsKey("AutoComplete") && $"{Attributes["AutoComplete"]}".ToLower() == "false" ? DefaultAutoCompleteAttribute :
|
||||
Attributes != null && Attributes.ContainsKey("AutoComplete") ? Attributes["AutoComplete"] as string ?? AutoCompleteType.GetAutoCompleteValue() : AutoCompleteType.GetAutoCompleteValue();
|
||||
get
|
||||
{
|
||||
if (Attributes != null && Attributes.TryGetValue("AutoComplete", out var value))
|
||||
{
|
||||
var v = (object?)value;
|
||||
var autoCompleteValue = v switch
|
||||
{
|
||||
bool boolValue => boolValue
|
||||
? AutoCompleteType.GetAutoCompleteValue()
|
||||
: DefaultAutoCompleteAttribute,
|
||||
string stringValue when bool.TryParse(stringValue, out var boolValue) => boolValue
|
||||
? AutoCompleteType.GetAutoCompleteValue()
|
||||
: DefaultAutoCompleteAttribute,
|
||||
AutoCompleteType typeValue => typeValue.GetAutoCompleteValue(),
|
||||
_ => value != null ? value.ToString() ?? AutoCompleteType.GetAutoCompleteValue() : AutoCompleteType.GetAutoCompleteValue()
|
||||
};
|
||||
|
||||
return string.Equals(autoCompleteValue, "false", StringComparison.OrdinalIgnoreCase)
|
||||
? DefaultAutoCompleteAttribute
|
||||
: autoCompleteValue;
|
||||
}
|
||||
|
||||
return AutoCompleteType.GetAutoCompleteValue();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -48,7 +70,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
public virtual string DefaultAutoCompleteAttribute { get; set; } = "off";
|
||||
|
||||
object ariaAutoComplete;
|
||||
object? ariaAutoComplete;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task SetParametersAsync(ParameterView parameters)
|
||||
@@ -56,10 +78,10 @@ namespace Radzen
|
||||
parameters = parameters.TryGetValue("aria-autocomplete", out ariaAutoComplete) ?
|
||||
ParameterView.FromDictionary(parameters
|
||||
.ToDictionary().Where(i => i.Key != "aria-autocomplete").ToDictionary(i => i.Key, i => i.Value)
|
||||
.ToDictionary(i => i.Key, i => i.Value))
|
||||
.ToDictionary(i => i.Key, i => (object?)i.Value))
|
||||
: parameters;
|
||||
|
||||
await base.SetParametersAsync(parameters);
|
||||
await base.SetParametersAsync(parameters).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -70,9 +92,11 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// Gets the aria-autocomplete attribute's string value.
|
||||
/// </summary>
|
||||
public virtual string AriaAutoCompleteAttribute
|
||||
public virtual string? AriaAutoCompleteAttribute
|
||||
{
|
||||
get => AutoCompleteAttribute == DefaultAutoCompleteAttribute ? DefaultAriaAutoCompleteAttribute : ariaAutoComplete as string;
|
||||
get => string.Equals(AutoCompleteAttribute, DefaultAutoCompleteAttribute, StringComparison.Ordinal)
|
||||
? DefaultAriaAutoCompleteAttribute
|
||||
: ariaAutoComplete as string;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -96,7 +120,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The component name.</value>
|
||||
[Parameter]
|
||||
public string Name { get; set; }
|
||||
public string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the tab order index for keyboard navigation.
|
||||
@@ -112,7 +136,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The placeholder.</value>
|
||||
[Parameter]
|
||||
public string Placeholder { get; set; }
|
||||
public string? Placeholder { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this <see cref="FormComponent{T}"/> is disabled.
|
||||
@@ -124,21 +148,21 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// The form
|
||||
/// </summary>
|
||||
IRadzenForm _form;
|
||||
IRadzenForm? _form;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the edit context.
|
||||
/// </summary>
|
||||
/// <value>The edit context.</value>
|
||||
[CascadingParameter]
|
||||
public EditContext EditContext { get; set; }
|
||||
public EditContext? EditContext { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the form.
|
||||
/// </summary>
|
||||
/// <value>The form.</value>
|
||||
[CascadingParameter]
|
||||
public IRadzenForm Form
|
||||
public IRadzenForm? Form
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -189,14 +213,14 @@ namespace Radzen
|
||||
/// <summary>
|
||||
/// The value
|
||||
/// </summary>
|
||||
protected T _value;
|
||||
protected T? _value;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the value.
|
||||
/// </summary>
|
||||
/// <value>The value.</value>
|
||||
[Parameter]
|
||||
public virtual T Value
|
||||
public virtual T? Value
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -230,7 +254,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <value>The value expression.</value>
|
||||
[Parameter]
|
||||
public Expression<Func<T>> ValueExpression { get; set; }
|
||||
public Expression<Func<T>>? ValueExpression { get; set; }
|
||||
/// <summary>
|
||||
/// Sets the parameters asynchronous.
|
||||
/// </summary>
|
||||
@@ -262,7 +286,7 @@ namespace Radzen
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender.</param>
|
||||
/// <param name="e">The <see cref="ValidationStateChangedEventArgs"/> instance containing the event data.</param>
|
||||
private void ValidationStateChanged(object sender, ValidationStateChangedEventArgs e)
|
||||
private void ValidationStateChanged(object? sender, ValidationStateChangedEventArgs e)
|
||||
{
|
||||
StateHasChanged();
|
||||
}
|
||||
@@ -280,19 +304,21 @@ namespace Radzen
|
||||
}
|
||||
|
||||
Form?.RemoveComponent(this);
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value.
|
||||
/// </summary>
|
||||
/// <returns>System.Object.</returns>
|
||||
public object GetValue()
|
||||
public object? GetValue()
|
||||
{
|
||||
return Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the <see cref="E:ContextMenu" /> event.
|
||||
/// Handles the ContextMenu event.
|
||||
/// </summary>
|
||||
/// <param name="args">The <see cref="MouseEventArgs"/> instance containing the event data.</param>
|
||||
/// <returns>Task.</returns>
|
||||
@@ -318,10 +344,10 @@ namespace Radzen
|
||||
|
||||
/// <summary> Provides support for RadzenFormField integration. </summary>
|
||||
[CascadingParameter]
|
||||
public IFormFieldContext FormFieldContext { get; set; }
|
||||
public IFormFieldContext? FormFieldContext { get; set; }
|
||||
|
||||
/// <summary> Gets the current placeholder. Returns empty string if this component is inside a RadzenFormField.</summary>
|
||||
protected string CurrentPlaceholder => FormFieldContext?.AllowFloatingLabel == true ? " " : Placeholder;
|
||||
protected string? CurrentPlaceholder => FormFieldContext?.AllowFloatingLabel == true ? " " : Placeholder;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public virtual async ValueTask FocusAsync()
|
||||
|
||||
@@ -10,6 +10,6 @@ public class FormInvalidSubmitEventArgs
|
||||
/// <summary>
|
||||
/// Gets the validation errors.
|
||||
/// </summary>
|
||||
public IEnumerable<string> Errors { get; set; }
|
||||
public IEnumerable<string>? Errors { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.JSInterop;
|
||||
@@ -18,7 +19,7 @@ namespace Radzen.Blazor
|
||||
/// </summary>
|
||||
/// <value>The child content.</value>
|
||||
[Parameter]
|
||||
public RenderFragment ChildContent
|
||||
public RenderFragment? ChildContent
|
||||
{
|
||||
get; set;
|
||||
}
|
||||
@@ -38,7 +39,7 @@ namespace Radzen.Blazor
|
||||
/// <summary>
|
||||
/// The width and height are set
|
||||
/// </summary>
|
||||
bool widthAndHeightAreSet = false;
|
||||
bool widthAndHeightAreSet;
|
||||
/// <summary>
|
||||
/// The first render
|
||||
/// </summary>
|
||||
@@ -57,7 +58,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
visibleChanged = false;
|
||||
|
||||
if (Visible)
|
||||
if (Visible && JSRuntime != null)
|
||||
{
|
||||
var rect = await JSRuntime.InvokeAsync<Rect>("Radzen.createGauge", Element, Reference);
|
||||
|
||||
@@ -117,23 +118,20 @@ namespace Radzen.Blazor
|
||||
double width = 0;
|
||||
double height = 0;
|
||||
|
||||
if (CurrentStyle.ContainsKey("height"))
|
||||
if (CurrentStyle.TryGetValue("height", out var pixelHeight))
|
||||
{
|
||||
var pixelHeight = CurrentStyle["height"];
|
||||
|
||||
if (pixelHeight.EndsWith("px"))
|
||||
if (pixelHeight.EndsWith("px", StringComparison.Ordinal))
|
||||
{
|
||||
height = Convert.ToDouble(pixelHeight.TrimEnd("px".ToCharArray()));
|
||||
height = Convert.ToDouble(pixelHeight.TrimEnd("px".ToCharArray()), CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentStyle.ContainsKey("width"))
|
||||
if (CurrentStyle.TryGetValue("width", out var pixelWidth))
|
||||
{
|
||||
var pixelWidth = CurrentStyle["width"];
|
||||
|
||||
if (pixelWidth.EndsWith("px"))
|
||||
if (pixelWidth.EndsWith("px", StringComparison.Ordinal))
|
||||
{
|
||||
width = Convert.ToDouble(pixelWidth.TrimEnd("px".ToCharArray()));
|
||||
width = Convert.ToDouble(pixelWidth.TrimEnd("px".ToCharArray()), CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +147,7 @@ namespace Radzen.Blazor
|
||||
/// <summary>
|
||||
/// The visible changed
|
||||
/// </summary>
|
||||
private bool visibleChanged = false;
|
||||
private bool visibleChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Set parameters as an asynchronous operation.
|
||||
@@ -166,7 +164,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (visibleChanged && !firstRender)
|
||||
{
|
||||
if (Visible == false)
|
||||
if (Visible == false && JSRuntime != null)
|
||||
{
|
||||
await JSRuntime.InvokeVoidAsync("Radzen.destroyGauge", Element);
|
||||
}
|
||||
@@ -185,10 +183,12 @@ namespace Radzen.Blazor
|
||||
{
|
||||
base.Dispose();
|
||||
|
||||
if (Visible)
|
||||
if (Visible && JSRuntime != null)
|
||||
{
|
||||
JSRuntime.InvokeVoid("Radzen.destroyGauge", Element);
|
||||
}
|
||||
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -8,6 +8,6 @@ public class GoogleMapClickEventArgs
|
||||
/// <summary>
|
||||
/// The position which represents the clicked map location.
|
||||
/// </summary>
|
||||
public GoogleMapPosition Position { get; set; }
|
||||
public GoogleMapPosition? Position { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ public class GoogleMapPosition : IEquatable<GoogleMapPosition>
|
||||
public double Lng { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool Equals(GoogleMapPosition other)
|
||||
public bool Equals(GoogleMapPosition? other)
|
||||
{
|
||||
if (other != null)
|
||||
{
|
||||
@@ -31,7 +31,7 @@ public class GoogleMapPosition : IEquatable<GoogleMapPosition>
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool Equals(object obj)
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return this.Equals(obj as GoogleMapPosition);
|
||||
}
|
||||
|
||||
@@ -9,13 +9,13 @@ public class Group
|
||||
/// Gets or sets the data.
|
||||
/// </summary>
|
||||
/// <value>The data.</value>
|
||||
public GroupResult Data { get; set; }
|
||||
public GroupResult Data { get; set; } = new GroupResult();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the group descriptor.
|
||||
/// </summary>
|
||||
/// <value>The group descriptor.</value>
|
||||
public GroupDescriptor GroupDescriptor { get; set; }
|
||||
public GroupDescriptor? GroupDescriptor { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the level.
|
||||
|
||||
@@ -9,7 +9,7 @@ public class GroupDescriptor
|
||||
/// Gets or sets the property to group by.
|
||||
/// </summary>
|
||||
/// <value>The property.</value>
|
||||
public string Property { get; set; }
|
||||
public string Property { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the sort order.
|
||||
@@ -21,13 +21,13 @@ public class GroupDescriptor
|
||||
/// Gets or sets the title displayed in the group.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
public string Title { get; set; }
|
||||
public string Title { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the format string used to display the key in the group.
|
||||
/// </summary>
|
||||
/// <value>The format string.</value>
|
||||
public string FormatString { get; set; }
|
||||
public string FormatString { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to show the footer for the group.
|
||||
|
||||
@@ -22,12 +22,12 @@ public class GroupResult
|
||||
/// <summary>
|
||||
/// The resulting elements in the group.
|
||||
/// </summary>
|
||||
public IEnumerable Items { get; internal set; }
|
||||
public IEnumerable? Items { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// The resulting subgroups in the group.
|
||||
/// </summary>
|
||||
public IEnumerable<GroupResult> Subgroups { get; internal set; }
|
||||
public IEnumerable<GroupResult>? Subgroups { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a <see cref="System.String" /> showing the key of the group and the number of items in the group.
|
||||
|
||||
@@ -15,7 +15,7 @@ public class GroupRowRenderEventArgs
|
||||
/// <summary>
|
||||
/// Gets the data item which the current row represents.
|
||||
/// </summary>
|
||||
public Group Group { get; internal set; }
|
||||
public Group? Group { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether this group row is expanded.
|
||||
|
||||
@@ -24,6 +24,6 @@ public class HtmlEditorExecuteEventArgs
|
||||
/// <summary>
|
||||
/// Gets the name of the command which RadzenHtmlEditor is executing.
|
||||
/// </summary>
|
||||
public string CommandName { get; set; }
|
||||
public string? CommandName { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,6 @@ public class HtmlEditorPasteEventArgs
|
||||
/// Gets or sets the HTML content that is pasted in RadzenHtmlEditor. Use the setter to filter unwanted markup from the pasted value.
|
||||
/// </summary>
|
||||
/// <value>The HTML.</value>
|
||||
public string Html { get; set; }
|
||||
public string? Html { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,9 @@ namespace Radzen
|
||||
/// <exception cref="Exception"></exception>
|
||||
/// <exception cref="Exception">Unable to parse the response.</exception>
|
||||
/// <exception cref="Exception"></exception>
|
||||
public static async Task<T> ReadAsync<T>(this HttpResponseMessage response)
|
||||
public static async Task<T?> ReadAsync<T>(this HttpResponseMessage response)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(response);
|
||||
try
|
||||
{
|
||||
response.EnsureSuccessStatusCode();
|
||||
@@ -42,7 +43,8 @@ namespace Radzen
|
||||
var responseAsString = await response.Content.ReadAsStringAsync();
|
||||
if (!string.IsNullOrEmpty(responseAsString))
|
||||
{
|
||||
if (response.Content.Headers.ContentType.MediaType == "application/json")
|
||||
var mediaType = response.Content.Headers.ContentType?.MediaType;
|
||||
if (string.Equals(mediaType, "application/json", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
JsonDocument json;
|
||||
try
|
||||
@@ -51,7 +53,7 @@ namespace Radzen
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("Unable to parse the response.");
|
||||
throw new InvalidOperationException("Unable to parse the response.");
|
||||
}
|
||||
|
||||
JsonElement error;
|
||||
@@ -60,13 +62,14 @@ namespace Radzen
|
||||
JsonElement message;
|
||||
if (error.TryGetProperty("message", out message))
|
||||
{
|
||||
throw new Exception(message.GetString());
|
||||
var messageText = message.GetString();
|
||||
throw new InvalidOperationException(messageText ?? "An error occurred.");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
XElement error = null;
|
||||
XElement? error = null;
|
||||
try
|
||||
{
|
||||
var xml = XDocument.Parse(responseAsString);
|
||||
@@ -82,12 +85,12 @@ namespace Radzen
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception("Unable to parse the response.");
|
||||
throw new InvalidOperationException("Unable to parse the response.");
|
||||
}
|
||||
|
||||
if (error != null)
|
||||
{
|
||||
throw new Exception(error.Value);
|
||||
throw new InvalidOperationException(error.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,14 +23,14 @@ public interface IAIChatService
|
||||
/// <param name="apiKey">Optional API key to override the configured API key.</param>
|
||||
/// <param name="apiKeyHeader">Optional API key header name to override the configured header.</param>
|
||||
/// <returns>An async enumerable that yields streaming response chunks from the AI model.</returns>
|
||||
IAsyncEnumerable<string> GetCompletionsAsync(string userInput, string sessionId = null, CancellationToken cancellationToken = default, string model = null, string systemPrompt = null, double? temperature = null, int? maxTokens = null, string endpoint = null, string proxy = null, string apiKey = null, string apiKeyHeader = null);
|
||||
IAsyncEnumerable<string> GetCompletionsAsync(string userInput, string? sessionId = null, CancellationToken cancellationToken = default, string? model = null, string? systemPrompt = null, double? temperature = null, int? maxTokens = null, string? endpoint = null, string? proxy = null, string? apiKey = null, string? apiKeyHeader = null);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or creates a conversation session.
|
||||
/// </summary>
|
||||
/// <param name="sessionId">The session ID. If null, a new session will be created.</param>
|
||||
/// <returns>The conversation session.</returns>
|
||||
ConversationSession GetOrCreateSession(string sessionId = null);
|
||||
ConversationSession GetOrCreateSession(string? sessionId = null);
|
||||
|
||||
/// <summary>
|
||||
/// Clears the conversation history for a specific session.
|
||||
|
||||
@@ -25,13 +25,13 @@ public interface IRadzenFormComponent
|
||||
/// Gets the value of the component.
|
||||
/// </summary>
|
||||
/// <returns>the value of the component - for example the text of RadzenTextBox.</returns>
|
||||
object GetValue();
|
||||
object? GetValue();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the component.
|
||||
/// </summary>
|
||||
/// <value>The name.</value>
|
||||
string Name { get; set; }
|
||||
string? Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the field identifier.
|
||||
@@ -58,6 +58,6 @@ public interface IRadzenFormComponent
|
||||
/// <summary>
|
||||
/// Sets the FormFieldContext of the component
|
||||
/// </summary>
|
||||
IFormFieldContext FormFieldContext { get; }
|
||||
IFormFieldContext? FormFieldContext { get; }
|
||||
}
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@ public class LegendClickEventArgs
|
||||
/// <summary>
|
||||
/// Gets the data at the clicked location.
|
||||
/// </summary>
|
||||
public object Data { get; set; }
|
||||
public object? Data { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the title of the clicked series. Determined by <see cref="CartesianSeries{TItem}.Title" />.
|
||||
/// </summary>
|
||||
/// <value>The title.</value>
|
||||
public string Title { get; set; }
|
||||
public string? Title { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the visibility of the clicked legend. Determined by <see cref="CartesianSeries{TItem}.IsVisible" />. Always visible for Pie Charts.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -20,10 +21,10 @@ namespace Radzen.Blazor
|
||||
|
||||
if (String.IsNullOrEmpty(format))
|
||||
{
|
||||
return value.ToString();
|
||||
return value.ToString() ?? String.Empty;
|
||||
}
|
||||
|
||||
return string.Format(format, value);
|
||||
return string.Format(CultureInfo.InvariantCulture, format, value);
|
||||
}
|
||||
|
||||
public override double Scale(double value, bool padding)
|
||||
@@ -96,7 +97,7 @@ namespace Radzen.Blazor
|
||||
{
|
||||
if (Step is IConvertible)
|
||||
{
|
||||
step = Convert.ToDouble(Step);
|
||||
step = Convert.ToDouble(Step, CultureInfo.InvariantCulture);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,7 +125,7 @@ namespace Radzen.Blazor
|
||||
|
||||
if (step == 0)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException("Step must be non-zero");
|
||||
throw new ArgumentOutOfRangeException(nameof(distance), "Step must be non-zero");
|
||||
}
|
||||
|
||||
return (start, end, Math.Abs(step));
|
||||
|
||||
@@ -10,6 +10,6 @@ public class ListBoxItemRenderEventArgs<TValue> : DropDownBaseItemRenderEventArg
|
||||
/// <summary>
|
||||
/// Gets the ListBox.
|
||||
/// </summary>
|
||||
public RadzenListBox<TValue> ListBox { get; internal set; }
|
||||
public RadzenListBox<TValue>? ListBox { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ public class LoadDataArgs
|
||||
/// <summary>
|
||||
/// Gets the sort expression as a string.
|
||||
/// </summary>
|
||||
public string OrderBy { get; set; }
|
||||
public string? OrderBy { get; set; }
|
||||
|
||||
private Func<string> getFilter;
|
||||
private Func<string>? getFilter;
|
||||
|
||||
internal Func<string> GetFilter
|
||||
internal Func<string>? GetFilter
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -40,19 +40,19 @@ public class LoadDataArgs
|
||||
}
|
||||
}
|
||||
|
||||
private string filter;
|
||||
private string? filter;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the filter expression as a string.
|
||||
/// </summary>
|
||||
/// <value>The filter.</value>
|
||||
public string Filter
|
||||
public string? Filter
|
||||
{
|
||||
get
|
||||
{
|
||||
if (filter == null && GetFilter != null)
|
||||
{
|
||||
filter = GetFilter();
|
||||
filter = GetFilter?.Invoke();
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
@@ -65,12 +65,12 @@ public class LoadDataArgs
|
||||
/// <summary>
|
||||
/// Gets the filter expression as a collection of filter descriptors.
|
||||
/// </summary>
|
||||
public IEnumerable<FilterDescriptor> Filters { get; set; }
|
||||
public IEnumerable<FilterDescriptor>? Filters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the sort expression as a collection of sort descriptors.
|
||||
/// </summary>
|
||||
/// <value>The sorts.</value>
|
||||
public IEnumerable<SortDescriptor> Sorts { get; set; }
|
||||
public IEnumerable<SortDescriptor>? Sorts { get; set; }
|
||||
}
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ public class LoginArgs
|
||||
/// <summary>
|
||||
/// Gets or sets the username.
|
||||
/// </summary>
|
||||
public string Username { get; set; }
|
||||
public string? Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the password.
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
public string? Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether the user wants to remember their credentials.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace Radzen;
|
||||
@@ -59,6 +60,8 @@ public class MD5
|
||||
/// <returns>The MD5 hash as a string.</returns>
|
||||
public static string Calculate(byte[] input)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(input);
|
||||
|
||||
uint a0 = 0x67452301; // A
|
||||
uint b0 = 0xefcdab89; // B
|
||||
uint c0 = 0x98badcfe; // C
|
||||
@@ -124,7 +127,7 @@ public class MD5
|
||||
|
||||
private static string GetByteString(uint x)
|
||||
{
|
||||
return String.Join("", BitConverter.GetBytes(x).Select(y => y.ToString("x2")));
|
||||
return String.Join("", BitConverter.GetBytes(x).Select(y => y.ToString("x2", CultureInfo.InvariantCulture)));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
using Microsoft.AspNetCore.Components.Rendering;
|
||||
@@ -194,7 +195,7 @@ internal class BlazorMarkdownRenderer(BlazorMarkdownRendererOptions options, Ren
|
||||
/// <inheritdoc />
|
||||
public override void VisitLink(Link link)
|
||||
{
|
||||
if (link.Destination.StartsWith("#"))
|
||||
if (link.Destination?.StartsWith('#') == true)
|
||||
{
|
||||
builder.OpenComponent<RadzenAnchor>(0);
|
||||
builder.AddAttribute(0, "href", link.Destination);
|
||||
@@ -210,7 +211,7 @@ internal class BlazorMarkdownRenderer(BlazorMarkdownRendererOptions options, Ren
|
||||
{
|
||||
builder.OpenComponent<RadzenLink>(0);
|
||||
|
||||
if (!HtmlSanitizer.IsDangerousUrl(link.Destination))
|
||||
if (!string.IsNullOrEmpty(link.Destination) && !HtmlSanitizer.IsDangerousUrl(link.Destination))
|
||||
{
|
||||
builder.AddAttribute(1, nameof(RadzenLink.Path), link.Destination);
|
||||
}
|
||||
@@ -230,7 +231,7 @@ internal class BlazorMarkdownRenderer(BlazorMarkdownRendererOptions options, Ren
|
||||
{
|
||||
builder.OpenComponent<RadzenImage>(0);
|
||||
|
||||
if (!HtmlSanitizer.IsDangerousUrl(image.Destination))
|
||||
if (!string.IsNullOrEmpty(image.Destination) && !HtmlSanitizer.IsDangerousUrl(image.Destination))
|
||||
{
|
||||
builder.AddAttribute(1, nameof(RadzenImage.Path), image.Destination);
|
||||
}
|
||||
@@ -291,7 +292,7 @@ internal class BlazorMarkdownRenderer(BlazorMarkdownRendererOptions options, Ren
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
var markerId = Convert.ToInt32(match.Groups[1].Value);
|
||||
var markerId = int.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture);
|
||||
outlet(builder, markerId);
|
||||
}
|
||||
else if (options.AllowHtml)
|
||||
@@ -349,11 +350,12 @@ internal class BlazorMarkdownRenderer(BlazorMarkdownRendererOptions options, Ren
|
||||
/// <inheritdoc />
|
||||
public override void VisitHtmlInline(HtmlInline htmlInline)
|
||||
{
|
||||
if (htmlInline.Value == null) return;
|
||||
var match = OutletRegex.Match(htmlInline.Value);
|
||||
|
||||
if (match.Success)
|
||||
{
|
||||
var markerId = Convert.ToInt32(match.Groups[1].Value);
|
||||
var markerId = Convert.ToInt32(match.Groups[1].Value, CultureInfo.InvariantCulture);
|
||||
outlet(builder, markerId);
|
||||
return;
|
||||
}
|
||||
@@ -406,7 +408,7 @@ internal class BlazorMarkdownRenderer(BlazorMarkdownRendererOptions options, Ren
|
||||
}
|
||||
}
|
||||
|
||||
if (html.EndsWith("/>") || IsVoidElement(tagName))
|
||||
if (html.EndsWith("/>", StringComparison.Ordinal) || IsVoidElement(tagName))
|
||||
{
|
||||
builder.CloseElement();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
@@ -29,6 +30,7 @@ public abstract class BlockContainer : Block
|
||||
/// <returns>The added block.</returns>
|
||||
public virtual T Add<T>(T block) where T : Block
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(block);
|
||||
children.Add(block);
|
||||
|
||||
block.Parent = this;
|
||||
@@ -43,6 +45,8 @@ public abstract class BlockContainer : Block
|
||||
/// <param name="target">The block to replace with.</param>
|
||||
public void Replace(Block source, Block target)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(source);
|
||||
ArgumentNullException.ThrowIfNull(target);
|
||||
var index = children.IndexOf(source);
|
||||
|
||||
if (index >= 0)
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
|
||||
@@ -9,6 +11,7 @@ public class BlockQuote : BlockContainer
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitBlockQuote(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -14,6 +16,7 @@ public class Code(string value) : Inline
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitCode(this);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -17,6 +19,7 @@ public class Document : BlockContainer
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitDocument(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,6 +10,7 @@ public class Emphasis : InlineContainer
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitEmphasis(this);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
@@ -10,17 +11,18 @@ public class FencedCodeBlock : Leaf
|
||||
/// <summary>
|
||||
/// The delimiter used to start and end the code block.
|
||||
/// </summary>
|
||||
public string Delimiter { get; private set; }
|
||||
public string? Delimiter { get; private set; }
|
||||
internal int Indent { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The info string of the code block. This is the first line of the code block and is used to specify the language of the code block.
|
||||
/// </summary>
|
||||
public string Info { get; private set; }
|
||||
public string? Info { get; private set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitFencedCodeBlock(this);
|
||||
}
|
||||
|
||||
@@ -29,7 +31,7 @@ public class FencedCodeBlock : Leaf
|
||||
base.Close(parser);
|
||||
|
||||
// first line becomes info string
|
||||
var newlinePos = Value.IndexOf('\n');
|
||||
var newlinePos = Value.IndexOf('\n', StringComparison.Ordinal);
|
||||
var firstLine = Value[..newlinePos];
|
||||
Info = firstLine.Trim();
|
||||
Value = Value[(newlinePos + 1)..];
|
||||
@@ -43,7 +45,7 @@ public class FencedCodeBlock : Leaf
|
||||
|
||||
var match = ClosingFenceRegex.Match(line);
|
||||
|
||||
if (indent <= 3 && parser.PeekNonSpace() == Delimiter[0] && match.Success && match.Length >= Delimiter.Length)
|
||||
if (indent <= 3 && Delimiter != null && parser.PeekNonSpace() == Delimiter[0] && match.Success && match.Length >= Delimiter.Length)
|
||||
{
|
||||
// closing fence - we're at end of line, so we can return
|
||||
parser.LastLineLength = parser.Offset + indent + match.Length;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -14,6 +16,7 @@ public abstract class Heading : Leaf
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitHeading(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
@@ -12,6 +13,7 @@ public class HtmlBlock : Leaf
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitHtmlBlock(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,12 +10,13 @@ public class HtmlInline : Inline
|
||||
/// <summary>
|
||||
/// Gets or sets the HTML element value.
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
public string? Value { get; set; }
|
||||
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitHtmlInline(this);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -78,7 +79,7 @@ class HtmlSanitizer
|
||||
|
||||
var safeAttributes = Regex.Replace(attributes, @"(\w+)\s*=\s*(""[^""]*""|'[^']*'|[^\s>]+)", SanitizeAttribute);
|
||||
|
||||
return $"<{(match.Value.StartsWith("</") ? "/" : "")}{tag}{safeAttributes}>";
|
||||
return $"<{(match.Value.StartsWith("</", StringComparison.Ordinal) ? "/" : "")}{tag}{safeAttributes}>";
|
||||
}
|
||||
|
||||
private string SanitizeAttribute(Match match)
|
||||
@@ -128,9 +129,9 @@ class HtmlSanitizer
|
||||
|
||||
var decoded = HtmlDecode(value).Trim().ToLowerInvariant();
|
||||
|
||||
return decoded.StartsWith("javascript:") ||
|
||||
decoded.StartsWith("vbscript:") ||
|
||||
decoded.StartsWith("data:text/html") ||
|
||||
decoded.Contains("expression(");
|
||||
return decoded.StartsWith("javascript:", StringComparison.Ordinal) ||
|
||||
decoded.StartsWith("vbscript:", StringComparison.Ordinal) ||
|
||||
decoded.StartsWith("data:text/html", StringComparison.Ordinal) ||
|
||||
decoded.Contains("expression(", StringComparison.Ordinal);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,16 +10,17 @@ public class Image : InlineContainer
|
||||
/// <summary>
|
||||
/// Gets or sets the destination (URL) of the image.
|
||||
/// </summary>
|
||||
public string Destination { get; set; }
|
||||
public string? Destination { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the alternative text of the image.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
public string? Title { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitImage(this);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -11,6 +12,7 @@ public class IndentedCodeBlock : Leaf
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitIndentedCodeBlock(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ class InlineParser
|
||||
public char Char { get; set; }
|
||||
public int Length { get; set; }
|
||||
public int Position { get; set; }
|
||||
public Text Node { get; set; }
|
||||
public Text? Node { get; set; }
|
||||
public bool CanOpen { get; set; }
|
||||
public bool CanClose { get; set; }
|
||||
public bool Active { get; set; } = true;
|
||||
@@ -296,7 +296,7 @@ class InlineParser
|
||||
|
||||
var url = destination.ToString();
|
||||
|
||||
if (url.Contains(Space))
|
||||
if (url.Contains(Space, StringComparison.Ordinal))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -778,7 +778,7 @@ class InlineParser
|
||||
|
||||
private void ReplaceOpener(int openerIndex, InlineContainer parent)
|
||||
{
|
||||
var startIndex = inlines.FindIndex(delimiters[openerIndex].Node.Equals);
|
||||
var startIndex = delimiters[openerIndex].Node != null ? inlines.FindIndex(node => node.Equals(delimiters[openerIndex].Node)) : -1;
|
||||
|
||||
ParseEmphasisAndStrong(openerIndex);
|
||||
|
||||
@@ -815,7 +815,7 @@ class InlineParser
|
||||
|
||||
AddTextNode();
|
||||
|
||||
var startIndex = inlines.FindIndex(delimiters[openerIndex].Node.Equals);
|
||||
var startIndex = delimiters[openerIndex].Node != null ? inlines.FindIndex(node => node.Equals(delimiters[openerIndex].Node)) : -1;
|
||||
|
||||
var endIndex = inlines.Count - startIndex;
|
||||
|
||||
@@ -878,8 +878,8 @@ class InlineParser
|
||||
{
|
||||
var closer = delimiters[closerIndex];
|
||||
var opener = delimiters[openerIndex];
|
||||
var startIndex = inlines.FindIndex(opener.Node.Equals);
|
||||
var endIndex = inlines.FindIndex(closer.Node.Equals);
|
||||
var startIndex = opener.Node != null ? inlines.FindIndex(opener.Node.Equals) : -1;
|
||||
var endIndex = closer.Node != null ? inlines.FindIndex(closer.Node.Equals) : -1;
|
||||
|
||||
if (startIndex >= 0 && endIndex >= 0)
|
||||
{
|
||||
@@ -896,7 +896,7 @@ class InlineParser
|
||||
|
||||
opener.Length -= charsToConsume;
|
||||
|
||||
if (opener.Length > 0)
|
||||
if (opener.Length > 0 && opener.Node != null)
|
||||
{
|
||||
opener.Node.Value = opener.Node.Value[..^charsToConsume];
|
||||
startIndex += 1;
|
||||
@@ -904,7 +904,7 @@ class InlineParser
|
||||
|
||||
closer.Length -= charsToConsume;
|
||||
|
||||
if (closer.Length > 0)
|
||||
if (closer.Length > 0 && closer.Node != null)
|
||||
{
|
||||
closer.Node.Value = closer.Node.Value[..^charsToConsume];
|
||||
endIndex -= 1;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,6 +10,7 @@ public class LineBreak : Inline
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitLineBreak(this);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,16 +10,17 @@ public class Link : InlineContainer
|
||||
/// <summary>
|
||||
/// Gets or sets the destination (URL) of the link.
|
||||
/// </summary>
|
||||
public string Destination { get; set; }
|
||||
public string? Destination { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the link title.
|
||||
/// </summary>
|
||||
public string Title { get; set; }
|
||||
public string? Title { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitLink(this);
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,6 @@ namespace Radzen.Blazor.Markdown;
|
||||
|
||||
class LinkReference
|
||||
{
|
||||
public string Destination { get; set; }
|
||||
public string Title { get; set; }
|
||||
public string? Destination { get; set; }
|
||||
public string? Title { get; set; }
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ public abstract class List : BlockContainer
|
||||
/// </summary>
|
||||
public bool Tight { get; set; } = true;
|
||||
internal int Padding { get; set; }
|
||||
internal string Delimiter { get; set; }
|
||||
internal string? Delimiter { get; set; }
|
||||
|
||||
internal override BlockMatch Matches(BlockParser parser)
|
||||
{
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
@@ -12,6 +14,7 @@ public class ListItem : BlockContainer
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitListItem(this);
|
||||
}
|
||||
|
||||
@@ -126,7 +129,7 @@ public class ListItem : BlockContainer
|
||||
var list = new OrderedList
|
||||
{
|
||||
MarkerOffset = parser.Indent,
|
||||
Start = int.Parse(match.Groups[1].Value),
|
||||
Start = int.Parse(match.Groups[1].Value, CultureInfo.InvariantCulture),
|
||||
Delimiter = match.Groups[2].Value
|
||||
};
|
||||
data = list;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
@@ -11,32 +12,56 @@ public abstract class NodeVisitorBase : INodeVisitor
|
||||
/// <summary>
|
||||
/// Visits a block quote by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitBlockQuote(BlockQuote blockQuote) => VisitChildren(blockQuote.Children);
|
||||
public virtual void VisitBlockQuote(BlockQuote blockQuote)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(blockQuote);
|
||||
VisitChildren(blockQuote.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a document by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitDocument(Document document) => VisitChildren(document.Children);
|
||||
public virtual void VisitDocument(Document document)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(document);
|
||||
VisitChildren(document.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a heading by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitHeading(Heading heading) => VisitChildren(heading.Children);
|
||||
public virtual void VisitHeading(Heading heading)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(heading);
|
||||
VisitChildren(heading.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a list item by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitListItem(ListItem listItem) => VisitChildren(listItem.Children);
|
||||
public virtual void VisitListItem(ListItem listItem)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(listItem);
|
||||
VisitChildren(listItem.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits an ordered list by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitOrderedList(OrderedList orderedList) => VisitChildren(orderedList.Children);
|
||||
public virtual void VisitOrderedList(OrderedList orderedList)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(orderedList);
|
||||
VisitChildren(orderedList.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a paragraph by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitParagraph(Paragraph paragraph) => VisitChildren(paragraph.Children);
|
||||
public virtual void VisitParagraph(Paragraph paragraph)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(paragraph);
|
||||
VisitChildren(paragraph.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a thematic break.
|
||||
@@ -83,27 +108,47 @@ public abstract class NodeVisitorBase : INodeVisitor
|
||||
/// <summary>
|
||||
/// Visits an ordered list by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitUnorderedList(UnorderedList unorderedList) => VisitChildren(unorderedList.Children);
|
||||
public virtual void VisitUnorderedList(UnorderedList unorderedList)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(unorderedList);
|
||||
VisitChildren(unorderedList.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits an emphasis by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitEmphasis(Emphasis emphasis) => VisitChildren(emphasis.Children);
|
||||
public virtual void VisitEmphasis(Emphasis emphasis)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(emphasis);
|
||||
VisitChildren(emphasis.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a strong by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitStrong(Strong strong) => VisitChildren(strong.Children);
|
||||
public virtual void VisitStrong(Strong strong)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(strong);
|
||||
VisitChildren(strong.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a link by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitLink(Link link) => VisitChildren(link.Children);
|
||||
public virtual void VisitLink(Link link)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(link);
|
||||
VisitChildren(link.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits an image by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitImage(Image image) => VisitChildren(image.Children);
|
||||
public virtual void VisitImage(Image image)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(image);
|
||||
VisitChildren(image.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a code block.
|
||||
@@ -129,28 +174,45 @@ public abstract class NodeVisitorBase : INodeVisitor
|
||||
/// <summary>
|
||||
/// Visits a table.
|
||||
/// </summary>
|
||||
public virtual void VisitTable(Table table) => VisitChildren(table.Rows);
|
||||
public virtual void VisitTable(Table table)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(table);
|
||||
VisitChildren(table.Rows);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a table header row by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitTableHeaderRow(TableHeaderRow header) => VisitChildren(header.Cells);
|
||||
public virtual void VisitTableHeaderRow(TableHeaderRow header)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(header);
|
||||
VisitChildren(header.Cells);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a table row by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitTableRow(TableRow row) => VisitChildren(row.Cells);
|
||||
public virtual void VisitTableRow(TableRow row)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(row);
|
||||
VisitChildren(row.Cells);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a table cell by visiting its children.
|
||||
/// </summary>
|
||||
public virtual void VisitTableCell(TableCell cell) => VisitChildren(cell.Children);
|
||||
public virtual void VisitTableCell(TableCell cell)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(cell);
|
||||
VisitChildren(cell.Children);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Visits a collection of nodes.
|
||||
/// </summary>
|
||||
protected void VisitChildren(IEnumerable<INode> children)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(children);
|
||||
foreach (var node in children)
|
||||
{
|
||||
node.Accept(this);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,6 +10,7 @@ public class OrderedList : List
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitOrderedList(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -9,6 +11,7 @@ public class Paragraph : Leaf
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitParagraph(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,6 +10,7 @@ public class SoftLineBreak : Inline
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitSoftLineBreak(this);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,6 +10,7 @@ public class Strong : InlineContainer
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitStrong(this);
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ public class Table : Leaf
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitTable(this);
|
||||
}
|
||||
|
||||
@@ -137,7 +138,7 @@ public class Table : Leaf
|
||||
|
||||
// Check if the line contains a pipe character to be more specific about table delimiters
|
||||
// This helps avoid misinterpreting heading delimiters as table delimiters
|
||||
if (!line.Contains('|') && !line.Contains(':'))
|
||||
if (!line.Contains('|', StringComparison.Ordinal) && !line.Contains(':', StringComparison.Ordinal))
|
||||
{
|
||||
return BlockStart.Skip;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
@@ -47,6 +48,7 @@ public class TableCell : INode, IBlockInlineContainer
|
||||
/// <inheritdoc />
|
||||
public void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitTableCell(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,6 +10,7 @@ public class TableHeaderRow : TableRow
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitTableHeaderRow(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
@@ -28,6 +29,7 @@ public class TableRow : INode
|
||||
/// <inheritdoc />
|
||||
public virtual void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitTableRow(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -13,6 +15,7 @@ public class Text(string value) : Inline
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitText(this);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
@@ -12,6 +13,7 @@ public class ThematicBreak : Block
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitThematicBreak(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System;
|
||||
|
||||
namespace Radzen.Blazor.Markdown;
|
||||
|
||||
/// <summary>
|
||||
@@ -8,6 +10,7 @@ public class UnorderedList : List
|
||||
/// <inheritdoc />
|
||||
public override void Accept(INodeVisitor visitor)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(visitor);
|
||||
visitor.VisitUnorderedList(this);
|
||||
}
|
||||
}
|
||||
@@ -10,16 +10,16 @@ public class MenuItemEventArgs : MouseEventArgs
|
||||
/// <summary>
|
||||
/// Gets text of the clicked item.
|
||||
/// </summary>
|
||||
public string Text { get; internal set; }
|
||||
public string? Text { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the value of the clicked item.
|
||||
/// </summary>
|
||||
public object Value { get; internal set; }
|
||||
public object? Value { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the path path of the clicked item.
|
||||
/// </summary>
|
||||
public string Path { get; internal set; }
|
||||
public string? Path { get; internal set; }
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user