added BlazorAppRadzenMultipleThemesDarkAndLightMode

This commit is contained in:
M. Akif Tokatlioglu
2024-04-27 23:03:12 +03:00
parent 28ae84b2c0
commit 6f32be1879
30 changed files with 1103 additions and 0 deletions

View File

@@ -0,0 +1,25 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.8.34601.278
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BlazorAppRadzenMultipleThemesDarkAndLightMode", "BlazorAppRadzenMultipleThemesDarkAndLightMode\BlazorAppRadzenMultipleThemesDarkAndLightMode.csproj", "{390ACA0D-7A2B-40B3-AE94-B69BC7A388AB}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{390ACA0D-7A2B-40B3-AE94-B69BC7A388AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{390ACA0D-7A2B-40B3-AE94-B69BC7A388AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{390ACA0D-7A2B-40B3-AE94-B69BC7A388AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{390ACA0D-7A2B-40B3-AE94-B69BC7A388AB}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E1A870CB-5B76-4FD7-B0D8-B18105899CCB}
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="8.0.4" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="8.0.4" />
<PackageReference Include="Radzen.Blazor" Version="4.30.2" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,24 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<base href="/" />
<link rel="stylesheet" href="bootstrap/bootstrap.min.css" />
@* THEME CSS *@
<Theme />
<link rel="icon" type="image/png" href="favicon.png" />
<HeadOutlet @rendermode="InteractiveServer" />
</head>
<body>
<Routes @rendermode="InteractiveServer" />
<script src="_content/Radzen.Blazor/Radzen.Blazor.js"></script>
<script src="_framework/blazor.web.js"></script>
</body>
</html>

View File

@@ -0,0 +1,70 @@
@inherits LayoutComponentBase
@inject IJSRuntime JSRuntime
@inject NavigationManager NavigationManager
@inject DialogService DialogService
@inject ContextMenuService ContextMenuService
@inject TooltipService TooltipService
@inject NotificationService NotificationService
<RadzenDialog />
<RadzenNotification />
<RadzenTooltip />
<RadzenContextMenu />
@* <RadzenComponents /> *@
<RadzenLayout style="grid-template-areas: 'rz-sidebar rz-header' 'rz-sidebar rz-body';">
<RadzenHeader>
<RadzenRow JustifyContent="JustifyContent.Start" AlignItems="AlignItems.Center" Gap="0">
<RadzenColumn Size="5">
<RadzenSidebarToggle Click="@SidebarToggleClick"></RadzenSidebarToggle>
</RadzenColumn>
<RadzenColumn Size="7">
<RadzenStack AlignItems="AlignItems.Center" Orientation="Orientation.Horizontal" JustifyContent="JustifyContent.End"
class="rz-mr-4">
<ThemeComponent />
</RadzenStack>
</RadzenColumn>
</RadzenRow>
</RadzenHeader>
<RadzenBody Expanded="@sidebarExpanded">
<RadzenRow class="rz-mx-auto rz-px-4 rz-pt-2 rz-pt-md-4 rz-pt-lg-6 rz-pt-xl-12 rz-pb-2 rz-pb-lg-12" Style="max-width: 1440px;">
<RadzenColumn Size="12">
@Body
</RadzenColumn>
</RadzenRow>
</RadzenBody>
<RadzenSidebar Expanded="@sidebarExpanded" style="z-index: 2">
<RadzenStack AlignItems="Radzen.AlignItems.Center" class="rz-py-4 rz-py-lg-6" Style="padding: var(--rz-panel-menu-item-padding); border-bottom: var(--rz-panel-menu-item-border);">
@* <RadzenImage Path="images/logo.png" style="width: 48px; height: 48px;"></RadzenImage>
*@
<RadzenText Text="appname" TextStyle="Radzen.Blazor.TextStyle.Subtitle1" class="rz-mb-0" style="color: var(--rz-sidebar-color);" />
</RadzenStack>
<NavMenu />
<RadzenStack AlignItems="Radzen.AlignItems.Center" Gap="0" class="rz-py-4 rz-py-lg-6" Style="padding: var(--rz-panel-menu-item-padding);">
<RadzenText Text="appname v1.0.0" TextStyle="Radzen.Blazor.TextStyle.Caption" style="color: var(--rz-text-disabled-color);" TagName="Radzen.Blazor.TagName.P" TextAlign="Radzen.TextAlign.Center" />
<RadzenText Text="Copyright Ⓒ 2024" TextStyle="Radzen.Blazor.TextStyle.Caption" class="rz-mb-0" style="color: var(--rz-text-disabled-color);" TagName="Radzen.Blazor.TagName.P" TextAlign="Radzen.TextAlign.Center" />
</RadzenStack>
</RadzenSidebar>
</RadzenLayout>
@code {
bool sidebarExpanded = true;
void SidebarToggleClick()
{
sidebarExpanded = !sidebarExpanded;
}
}

View File

@@ -0,0 +1,7 @@
<RadzenPanelMenu>
<RadzenPanelMenuItem Text="Home" Path="/" />
<RadzenPanelMenuItem Text="Posts" Path="/BlogPost" />
</RadzenPanelMenu>

View File

@@ -0,0 +1,77 @@
@page "/BlogPost/Create"
<RadzenText Text="Create" TextStyle="TextStyle.H5" />
@if (blogPostViewModel == null)
{
<p>Loading...</p>
}
else
{
<RadzenStack>
<RadzenFieldset Text="New Post">
<RadzenStack Gap="2rem">
<EditForm Context="editFormNewPost" Model="@blogPostViewModel" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Title" for="title" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<InputText id="title" class="form-control" placeholder="Title"
@bind-Value="blogPostViewModel.Title" />
<ValidationMessage For="@(() => blogPostViewModel.Title)" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Content" for="content" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<InputText id="content" class="form-control" placeholder="Content"
@bind-Value="blogPostViewModel.Content" />
<ValidationMessage For="@(() => blogPostViewModel.Content)" />
</RadzenColumn>
</RadzenRow>
<RadzenButton Text="Save" Icon="save"
ButtonType="ButtonType.Submit" ButtonStyle="ButtonStyle.Success" />
</EditForm>
</RadzenStack>
</RadzenFieldset>
</RadzenStack>
<RadzenButton Text="Back" Icon="arrow_back" Class="rz-mt-2"
Click="NavigatetoBlogPostIndex"
ButtonStyle="ButtonStyle.Primary" />
}
@code {
private BlogPostViewModel? blogPostViewModel;
protected override void OnInitialized()
{
blogPostViewModel = new();
}
protected async Task HandleValidSubmit()
{
if (blogPostViewModel == null) return;
var blogPost = Mapper.Map<BlogPostViewModel, BlogPost>(blogPostViewModel);
bool result = await BlogPostService.AddBlogPostAsync(blogPost);
if (result)
NavigationManager.NavigateTo("/BlogPost/");
}
private void NavigatetoBlogPostIndex() => NavigationManager.NavigateTo("/BlogPost");
}

View File

@@ -0,0 +1,85 @@
@page "/BlogPost/Delete/{id:int}"
<h3>Delete</h3>
@if (blogPostViewModel == null)
{
<p>Loading...</p>
}
else
{
<RadzenStack>
<RadzenFieldset Text="Post Delete">
<RadzenStack>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Id" for="id" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="id" class="form-control" placeholder="Id" ReadOnly=true
Value="@blogPostViewModel.Id.ToString()" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Title" for="title" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="title" class="form-control" placeholder="Title" ReadOnly=true
Value="@blogPostViewModel.Title" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
<RadzenButton Text="REMOVE" Icon="delete_forever" ButtonStyle="ButtonStyle.Danger"
Click="RemoveButtonClick" />
</RadzenFieldset>
</RadzenStack>
<RadzenButton Text="Back" Icon="arrow_back" Class="rz-mt-2"
Click="NavigatetoBlogPostIndex"
ButtonStyle="ButtonStyle.Primary" />
}
@code {
[Parameter]
public int id { get; set; }
BlogPostViewModel? blogPostViewModel;
protected override async Task OnInitializedAsync()
{
if (blogPostViewModel == null)
{
var blogPost = await BlogPostService.GetbyId(id);
if (blogPost == null)
return;
blogPostViewModel = Mapper.Map<BlogPost, BlogPostViewModel>(blogPost);
}
}
private async void RemoveButtonClick()
{
bool result = await BlogPostService.DeletebyIdAsync(id);
if (result)
NavigationManager.NavigateTo("/BlogPost");
}
private void NavigatetoBlogPostIndex() => NavigationManager.NavigateTo("/BlogPost");
}

View File

@@ -0,0 +1,78 @@
@page "/BlogPost/Detail/{id:int}"
<h3>Detail</h3>
@if (blogPostViewModel == null)
{
<p>Loading...</p>
}
else
{
<RadzenStack>
<RadzenFieldset Text="Post Detail">
<RadzenStack>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Id" for="id" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="id" class="form-control" placeholder="Id" ReadOnly=true
Value="@blogPostViewModel.Id.ToString()" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Title" for="title" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="title" class="form-control" placeholder="Title" ReadOnly=true
Value="@blogPostViewModel.Title" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Content" for="content" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<RadzenTextBox id="content" class="form-control" placeholder="Content" ReadOnly=true
Value="@blogPostViewModel.Content" />
</RadzenColumn>
</RadzenRow>
</RadzenStack>
</RadzenFieldset>
</RadzenStack>
<RadzenButton Text="Back" Icon="arrow_back" Class="rz-mt-2"
Click="NavigatetoBlogPostIndex"
ButtonStyle="ButtonStyle.Primary" />
}
@code {
[Parameter]
public int id { get; set; }
BlogPostViewModel? blogPostViewModel;
protected override async Task OnInitializedAsync()
{
if (blogPostViewModel == null)
{
var blogPost = await BlogPostService.GetbyId(id);
if (blogPost == null)
return;
blogPostViewModel = Mapper.Map<BlogPost, BlogPostViewModel>(blogPost);
}
}
private void NavigatetoBlogPostIndex() => NavigationManager.NavigateTo("/BlogPost");
}

View File

@@ -0,0 +1,87 @@
@page "/BlogPost/Edit/{id:int}"
<h3>Edit</h3>
@if (blogPostViewModel == null)
{
<p>Loading...</p>
}
else
{
<RadzenStack>
<RadzenFieldset Text="Edit Post">
<RadzenStack Gap="2rem">
<EditForm Context="editFormEdit" Model="@blogPostViewModel" OnValidSubmit="HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Title" for="title" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<InputText id="title" class="form-control" placeholder="Title"
@bind-Value="blogPostViewModel.Title" />
<ValidationMessage For="@(() => blogPostViewModel.Title)" />
</RadzenColumn>
</RadzenRow>
<RadzenRow AlignItems="AlignItems.Center" Class="rz-mb-2">
<RadzenColumn SizeSM="12" SizeMD="2" SizeLG="2">
<RadzenLabel Text="Content" for="content" />
</RadzenColumn>
<RadzenColumn SizeSM="12" SizeMD="10" SizeLG="10">
<InputText id="content" class="form-control" placeholder="Content"
@bind-Value="blogPostViewModel.Content" />
<ValidationMessage For="@(() => blogPostViewModel.Content)" />
</RadzenColumn>
</RadzenRow>
<RadzenButton Text="Save" Icon="save"
ButtonType="ButtonType.Submit" ButtonStyle="ButtonStyle.Success" />
</EditForm>
</RadzenStack>
</RadzenFieldset>
</RadzenStack>
<RadzenButton Text="Back" Icon="arrow_back" Class="rz-mt-2"
Click="NavigatetoBlogPostIndex"
ButtonStyle="ButtonStyle.Primary" />
}
@code {
[Parameter]
public int id { get; set; }
BlogPostViewModel? blogPostViewModel;
protected override async Task OnInitializedAsync()
{
if (blogPostViewModel == null)
{
var blogPost = await BlogPostService.GetbyId(id);
if (blogPost == null)
return;
blogPostViewModel = Mapper.Map<BlogPost, BlogPostViewModel>(blogPost);
}
}
protected async Task HandleValidSubmit()
{
if (blogPostViewModel == null) return;
var blogPost = Mapper.Map<BlogPostViewModel, BlogPost>(blogPostViewModel);
bool result = await BlogPostService.UpdateBlogPostAsync(id, blogPost);
if (result)
NavigationManager.NavigateTo("/BlogPost/");
}
private void NavigatetoBlogPostIndex() => NavigationManager.NavigateTo("/BlogPost");
}

View File

@@ -0,0 +1,81 @@
@page "/BlogPost"
<PageTitle>Posts</PageTitle>
<RadzenRow>
<RadzenColumn SizeSM="12" SizeMD="12" SizeLG="4">
<RadzenStack Orientation="Orientation.Horizontal" AlignItems="AlignItems.Center">
<RadzenText Text="Posts" TextStyle="TextStyle.H5" />
<RadzenButton Text="Create" Icon="add_circle_outline"
Click="NavigatetoCreate"
ButtonStyle="ButtonStyle.Success" class="rz-mb-2 rz-p-2" />
</RadzenStack>
</RadzenColumn>
</RadzenRow>
<RadzenDataGrid KeyProperty="Id" IsLoading="@isLoading" ShowPagingSummary=true
Count="@totalCount" Data="@blogPosts" LoadData="@LoadData"
FilterPopupRenderMode="PopupRenderMode.OnDemand"
FilterCaseSensitivity="FilterCaseSensitivity.CaseInsensitive"
FilterMode="FilterMode.Advanced" AllowSorting="true" AllowFiltering="true"
AllowPaging="true" PageSize="@itemPageSize" PagerHorizontalAlign="HorizontalAlign.Center"
TItem="BlogPostViewModel" ColumnWidth="200px">
<Columns>
<RadzenDataGridColumn TItem="BlogPostViewModel" Property="Id" Filterable="false" Title="Id" Frozen="true" Width="30px" MinWidth="30px" TextAlign="TextAlign.Center" />
<RadzenDataGridColumn TItem="BlogPostViewModel" Property="Title" Title="Title" />
<RadzenDataGridColumn TItem="BlogPostViewModel" Property="Content" Title="Content" />
<RadzenDataGridColumn TItem="BlogPostViewModel" Context="blogPost" Filterable="false" Sortable="false" Width="150px" TextAlign="TextAlign.Center">
<Template Context="blogPost">
<RadzenRow JustifyContent="JustifyContent.Center">
<RadzenButton Icon="pageview" ButtonStyle="ButtonStyle.Info" Variant="Variant.Flat" Size="ButtonSize.Medium"
Click="@(args => NavigatetoDetail(blogPost.Id))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton Icon="edit" ButtonStyle="ButtonStyle.Warning" Variant="Variant.Flat" Size="ButtonSize.Medium"
Click="@(args => NavigatetoEdit(blogPost.Id))" @onclick:stopPropagation="true">
</RadzenButton>
<RadzenButton Icon="delete_forever" ButtonStyle="ButtonStyle.Danger" Variant="Variant.Flat" Size="ButtonSize.Medium"
Click="@(args => NavigatetoDelete(blogPost.Id))" @onclick:stopPropagation="true">
</RadzenButton>
</RadzenRow>
</Template>
</RadzenDataGridColumn>
</Columns>
</RadzenDataGrid>
@code {
const int itemPageSize = 10;
private bool isLoading;
private int totalCount;
private IEnumerable<BlogPostViewModel>? blogPosts;
private async Task LoadData(LoadDataArgs args)
{
isLoading = true;
var result = await BlogPostService.GetBlogPostsAsync(filter: args.Filter, top: args.Top, skip: args.Skip, orderby: args.OrderBy, count: true);
blogPosts = Mapper.Map<IEnumerable<BlogPost>, IEnumerable<BlogPostViewModel>>(result.Result);
totalCount = result.TotalCount;
isLoading = false;
}
private void NavigatetoCreate() => NavigationManager.NavigateTo("/BlogPost/Create");
private void NavigatetoDetail(int id) => NavigationManager.NavigateTo($"/BlogPost/Detail/{id}");
private void NavigatetoEdit(int id) => NavigationManager.NavigateTo($"/BlogPost/Edit/{id}");
private void NavigatetoDelete(int id) => NavigationManager.NavigateTo($"/BlogPost/Delete/{id}");
}

View File

@@ -0,0 +1,9 @@
@using AutoMapper
@using BlazorAppRadzenMultipleThemesDarkAndLightMode.Data;
@using BlazorAppRadzenMultipleThemesDarkAndLightMode.Models;
@using BlazorAppRadzenMultipleThemesDarkAndLightMode.Services;
@using BlazorAppRadzenMultipleThemesDarkAndLightMode.ViewModels;
@inject IMapper Mapper
@inject NavigationManager NavigationManager
@inject BlogPostService BlogPostService

View File

@@ -0,0 +1,36 @@
@page "/Error"
@using System.Diagnostics
<PageTitle>Error</PageTitle>
<h1 class="text-danger">Error.</h1>
<h2 class="text-danger">An error occurred while processing your request.</h2>
@if (ShowRequestId)
{
<p>
<strong>Request ID:</strong> <code>@RequestId</code>
</p>
}
<h3>Development Mode</h3>
<p>
Swapping to <strong>Development</strong> environment will display more detailed information about the error that occurred.
</p>
<p>
<strong>The Development environment shouldn't be enabled for deployed applications.</strong>
It can result in displaying sensitive information from exceptions to end users.
For local debugging, enable the <strong>Development</strong> environment by setting the <strong>ASPNETCORE_ENVIRONMENT</strong> environment variable to <strong>Development</strong>
and restarting the app.
</p>
@code{
[CascadingParameter]
private HttpContext? HttpContext { get; set; }
private string? RequestId { get; set; }
private bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
protected override void OnInitialized() =>
RequestId = Activity.Current?.Id ?? HttpContext?.TraceIdentifier;
}

View File

@@ -0,0 +1,7 @@
@page "/"
<PageTitle>Home</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.

View File

@@ -0,0 +1,6 @@
<Router AppAssembly="typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="routeData" DefaultLayout="typeof(Layout.MainLayout)" />
@* <FocusOnNavigate RouteData="routeData" Selector="h1" /> *@
</Found>
</Router>

View File

@@ -0,0 +1,27 @@
@inject NavigationManager NavigationManager
@inject ThemeService ThemeService
<link href="@Href" rel="stylesheet" />
@*
//////// THEMES
<link rel="stylesheet" href="_content/Radzen.Blazor/css/default.css">
<link rel="stylesheet" href="_content/Radzen.Blazor/css/dark.css">
<link rel="stylesheet" href="_content/Radzen.Blazor/css/humanistic.css">
<link rel="stylesheet" href="_content/Radzen.Blazor/css/software.css">
<link rel="stylesheet" href="_content/Radzen.Blazor/css/standard.css">
<link rel="stylesheet" href="_content/Radzen.Blazor/css/material-base.css">
*@
@code {
//string Href => $"_content/Radzen.Blazor/css/{ThemeService.CurrentTheme}-base.css";
string Href => $"_content/Radzen.Blazor/css/{ThemeService.CurrentTheme}.css";
protected override void OnInitialized()
{
#if !RADZEN
ThemeService.Initialize(NavigationManager);
#endif
}
}

View File

@@ -0,0 +1,23 @@
@inject ThemeService ThemeService
@inject NavigationManager UriHelper
<RadzenLabel Text="Select Theme" Component="DropDownTextValueProperties" class="rz-mr-2" />
<RadzenDropDown TValue="string"
Value="@ThemeService.CurrentTheme" Data="@ThemeService.Themes"
TextProperty="Text" ValueProperty="Value"
Name="DropDownTextValueProperties"
Change="@ChangeTheme" />
@code {
protected override void OnInitialized()
{
ThemeService.Initialize(UriHelper);
}
void ChangeTheme(object value)
{
ThemeService.Change(UriHelper, $"{value}");
}
}

View File

@@ -0,0 +1,13 @@
@using System.Net.Http
@using System.Net.Http.Json
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.AspNetCore.Components.Web
@using static Microsoft.AspNetCore.Components.Web.RenderMode
@using Microsoft.AspNetCore.Components.Web.Virtualization
@using Microsoft.JSInterop
@using BlazorAppRadzenMultipleThemesDarkAndLightMode
@using BlazorAppRadzenMultipleThemesDarkAndLightMode.Components
@using Radzen
@using Radzen.Blazor

View File

@@ -0,0 +1,19 @@
using BlazorAppRadzenMultipleThemesDarkAndLightMode.Models;
using Microsoft.EntityFrameworkCore;
namespace BlazorAppRadzenMultipleThemesDarkAndLightMode.Data;
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<BlogPost> BlogPosts => Set<BlogPost>();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
}

View File

@@ -0,0 +1,101 @@
using BlazorAppRadzenMultipleThemesDarkAndLightMode.Models;
namespace BlazorAppRadzenMultipleThemesDarkAndLightMode.Data;
public class SeedData
{
private readonly ApplicationDbContext _context;
public SeedData(ApplicationDbContext context)
{
_context = context;
}
public async Task CreateInitialData()
{
var posts = GetAllBlogPosts();
await _context.BlogPosts.AddRangeAsync(posts);
await _context.SaveChangesAsync();
}
private static IEnumerable<BlogPost> GetAllBlogPosts()
{
List<BlogPost> posts = new();
for (int i = 0; i < 50; i++)
{
BlogPost post = new() { Id = i + 1, Title = titles[i], Content = contents[i % 10] };
posts.Add(post);
}
return posts;
}
private static readonly string[] titles = {
"Introduction to Object-Oriented Programming",
"Mastering Data Structures and Algorithms",
"Building Web Applications with ASP.NET",
"Creating Mobile Apps with Xamarin",
"Exploring Artificial Intelligence and Machine Learning",
"Understanding Functional Programming Concepts",
"Developing Games with Unity",
"Securing Web Applications from Cyber Attacks",
"Optimizing Code Performance for Better Efficiency",
"Implementing Design Patterns in Software Development",
"Testing and Debugging Strategies for Reliable Software",
"Working with Databases and SQL",
"Building Responsive User Interfaces with HTML and CSS",
"Exploring Cloud Computing and Serverless Architecture",
"Developing Cross-Platform Applications with React Native",
"Introduction to Internet of Things (IoT)",
"Creating Scalable Microservices with Docker and Kubernetes",
"Understanding Network Protocols and TCP/IP",
"Building RESTful APIs with Node.js and Express",
"Exploring Big Data Analytics and Apache Hadoop",
"Mastering Version Control with Git and GitHub",
"Developing Desktop Applications with WPF",
"Securing Mobile Applications from Malicious Attacks",
"Optimizing Database Performance with Indexing",
"Implementing Continuous Integration and Deployment",
"Testing Mobile Apps on Different Platforms",
"Working with NoSQL Databases like MongoDB",
"Building Progressive Web Apps with React",
"Exploring Quantum Computing and Quantum Algorithms",
"Introduction to Cybersecurity and Ethical Hacking",
"Creating Chatbots with Natural Language Processing",
"Understanding Software Development Life Cycle",
"Developing Augmented Reality (AR) Applications",
"Securing Web APIs with OAuth and JWT",
"Optimizing Front-End Performance for Better User Experience",
"Implementing Machine Learning Models with TensorFlow",
"Testing Web Applications for Cross-Browser Compatibility",
"Working with Blockchain Technology and Smart Contracts",
"Building Real-Time Applications with SignalR",
"Exploring Cryptography and Encryption Techniques",
"Introduction to Agile Software Development",
"Creating Voice User Interfaces with Amazon Alexa",
"Understanding Web Accessibility and Inclusive Design",
"Developing Natural Language Processing Applications",
"Securing Cloud Infrastructure and Services",
"Optimizing Backend Performance for Scalability",
"Implementing Continuous Monitoring and Alerting",
"Testing APIs with Postman and Swagger",
"Working with Data Visualization Libraries like D3.js",
"Building E-commerce Applications with Shopify",
"Exploring Robotic Process Automation (RPA)",
"Introduction to DevOps and CI/CD Pipelines"
};
private static readonly string[] contents = new string[]
{
"Lorem ipsum dolor sit amet, consectetur t.",
"Sed ut perspiciatis unde omnis iste natuccusantium doloremque laudantium.",
"Nemo enim ipsam voluptatem quia voluptas aut fugit.",
"Quis autem vel eum iure reprehenderit quesse quam nihil molestiae consequatur.",
"At vero eos et accusamus et iusto odio d.",
"Similique sunt in culpa qui officia de.",
"Et harum quidem rerum facilis est et expio.",
"Nam libero tempore, cum soluta nobis est.",
"Omnis voluptas assumenda est, omnis dolo",
"Temporibus autem quibusdam et aut offic"
};
}

View File

@@ -0,0 +1,8 @@
namespace BlazorAppRadzenMultipleThemesDarkAndLightMode.Models;
public class BlogPost
{
public int Id { get; set; }
public string Title { get; set; } = string.Empty;
public string Content { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,92 @@
using AutoMapper;
using BlazorAppRadzenMultipleThemesDarkAndLightMode;
using BlazorAppRadzenMultipleThemesDarkAndLightMode.Components;
using BlazorAppRadzenMultipleThemesDarkAndLightMode.Data;
using BlazorAppRadzenMultipleThemesDarkAndLightMode.Models;
using BlazorAppRadzenMultipleThemesDarkAndLightMode.Services;
using BlazorAppRadzenMultipleThemesDarkAndLightMode.ViewModels;
using Microsoft.EntityFrameworkCore;
using Radzen;
internal class Program
{
private static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddDbContext<ApplicationDbContext>(options =>
options.UseInMemoryDatabase("ConnectionInMemory")
);
builder.Services.AddScoped<SeedData>();
builder.Services.AddScoped<BlogPostService>();
// Radzen Services
builder.Services.AddScoped<DialogService>();
builder.Services.AddScoped<NotificationService>();
builder.Services.AddScoped<TooltipService>();
builder.Services.AddScoped<ContextMenuService>();
// ADDED FOR THEME SUPPORT
builder.Services.AddScoped<ThemeService>();
var mapperConfiguration = new MapperConfiguration(configuration =>
{
var profile = new MappingProfile();
configuration.AddProfile(profile);
});
var mapper = mapperConfiguration.CreateMapper();
builder.Services.AddSingleton(mapper);
builder.Services.CreateDatabase().GetAwaiter().GetResult();
builder.Services.AddDatabaseDeveloperPageExceptionFilter();
// Add services to the container.
builder.Services.AddRazorComponents()
.AddInteractiveServerComponents();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error", createScopeForErrors: true);
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAntiforgery();
app.MapRazorComponents<App>()
.AddInteractiveServerRenderMode();
app.Run();
}
}
public static class ServiceCollectionExtensions
{
public static async Task CreateDatabase(this IServiceCollection services)
{
using (IServiceScope tmp = services.BuildServiceProvider().CreateScope())
{
await using var _context = tmp.ServiceProvider.GetRequiredService<ApplicationDbContext>();
var seedData = tmp.ServiceProvider.GetRequiredService<SeedData>();
await seedData.CreateInitialData();
}
}
}
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<BlogPost, BlogPostViewModel>().ReverseMap();
}
}

View File

@@ -0,0 +1,14 @@
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"profiles": {
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

View File

@@ -0,0 +1,90 @@
using BlazorAppRadzenMultipleThemesDarkAndLightMode.Data;
using BlazorAppRadzenMultipleThemesDarkAndLightMode.Models;
using Microsoft.EntityFrameworkCore;
using Radzen;
using System.Linq.Dynamic.Core;
namespace BlazorAppRadzenMultipleThemesDarkAndLightMode.Services;
public class BlogPostService
{
private readonly ApplicationDbContext _context;
public BlogPostService(ApplicationDbContext context)
{
_context = context;
}
public Task<BlogPost?> GetbyId(int id)
{
return _context.BlogPosts.FirstOrDefaultAsync(x => x.Id == id);
}
public async Task<(IEnumerable<BlogPost> Result, int TotalCount)> GetBlogPostsAsync(string? filter = default, int? top = default, int? skip = default, string? orderby = default, string? expand = default, string? select = default, bool? count = default)
{
var query = _context.BlogPosts.AsQueryable();
if (!string.IsNullOrEmpty(filter))
query = query.Where(filter);
if (!string.IsNullOrEmpty(orderby))
query = query.OrderBy(orderby);
int totalCount = 0;
if (count == true)
totalCount = query.Count();
IEnumerable<BlogPost>? result;
if (skip == null || top == null)
result = await query.ToListAsync();
else
result = await query.Skip(skip.Value).Take(top.Value).ToListAsync();
return (result, totalCount);
}
public async Task<bool> AddBlogPostAsync(BlogPost blogPost)
{
try
{
await _context.BlogPosts.AddAsync(blogPost);
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
return false;
}
return true;
}
public async Task<bool> UpdateBlogPostAsync(int id, BlogPost blogPost)
{
try
{
var oldBlogPost = _context.BlogPosts.FirstOrDefault(x => x.Id == id);
if (oldBlogPost == null) return false;
oldBlogPost.Title = blogPost.Title;
oldBlogPost.Content = blogPost.Content;
await _context.SaveChangesAsync();
}
catch (Exception ex)
{
return false;
}
return true;
}
public async Task<bool> DeletebyIdAsync(int id)
{
var blogPost = await _context.BlogPosts.FirstOrDefaultAsync(x => x.Id == id);
if (blogPost == null)
return false;
_context.BlogPosts.Remove(blogPost);
await _context.SaveChangesAsync();
return true;
}
}

View File

@@ -0,0 +1,65 @@
using System.Web;
using Microsoft.AspNetCore.Components;
namespace BlazorAppRadzenMultipleThemesDarkAndLightMode;
public class ThemeService
{
public class Theme
{
public string Text { get; set; }
public string Value { get; set; }
}
public static readonly Theme[] Themes = new[]
{
new Theme {
Text = "Material",
Value = "material"
},
new Theme {
Text = "Standard",
Value = "standard"
},
new Theme {
Text = "Default",
Value = "default"
},
new Theme {
Text = "Humanistic",
Value = "humanistic"
},
new Theme {
Text = "Software",
Value = "software"
},
new Theme {
Text = "Dark",
Value="dark"
}
};
public const string DefaultTheme = "standard";
public const string QueryParameter = "theme";
public string CurrentTheme { get; set; } = DefaultTheme;
public void Initialize(NavigationManager navigationManager)
{
var uri = new Uri(navigationManager.ToAbsoluteUri(navigationManager.Uri).ToString());
var query = HttpUtility.ParseQueryString(uri.Query);
var value = query.Get(QueryParameter);
if (Themes.Any(theme => theme.Value == value))
{
CurrentTheme = value;
}
}
public void Change(NavigationManager navigationManager, string theme)
{
var url = navigationManager.GetUriWithQueryParameters(navigationManager.Uri,
new Dictionary<string, object>() { { QueryParameter, theme } });
navigationManager.NavigateTo(url, true);
}
}

View File

@@ -0,0 +1,18 @@
using System.ComponentModel.DataAnnotations;
namespace BlazorAppRadzenMultipleThemesDarkAndLightMode.ViewModels;
public class BlogPostViewModel
{
public int Id { get; set; }
[Required(AllowEmptyStrings = false, ErrorMessage = "Title can not be empty")]
public string Title { get; set; } = string.Empty;
[Required(AllowEmptyStrings = false, ErrorMessage = "Content can not be empty")]
public string Content { get; set; } = string.Empty;
public string TitleShort { get; set; } = string.Empty;
public string ContentShort { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,8 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}

View File

@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}