This blog is not a tutorial on software / web development like I usually create. The purpose of this post is to serve as the Help page for using a site I just published called PixelDatabase.Net.
For C# Programmers
Although I stated this blog is not for programmers, most of the code used / talked about is open source:
* The source code for the website PixelDatabase.Net is not published as I plan on accepting donations and / or advertisements since open source does not pay very well and I am unemployed.
Pixel Database.Net
PixelDatabase.Net reads in a .jpg or .png and creates a Pixel Information Database, that can be manipulated in a language I invented called BQL or Bitmap Query language.
Motivation
The reason I wrote Transparency Maker is when I purchase stock photos, almost all come with a background color and often I need a transparent background. There are other tools that perform background removal, with more now than in 2012 when I started working on Transparency Maker, however I wanted a way to programmaticaly manipulate pixels.
Web Version
Fast forward to 2020 and Blazor is my new favorite development environment. Most of the features work the same in the web version as the Windows Forms version. A few things are different in the web version, with the biggest being every time the file is edited I must save the file to disc with some random characters added to the file name and reload.
How To Use PixelDatabase.Net
3.28.2020: More to come, but I need the URL so I can publish the site while I work on the documentation.
Description: This tutorial will guide you step by step through creating a complete Blazor application that includes many features that would be needed for a real world site, including:
1. Creating a Blazor project from scratch
2. Creating a SQL Server Database with two tables: Artist, Image
3. Creating some images with my open source project Random Art
4. Building the data tier with DataTier.Net and execute the generated stored procedures
5. Uploading images with DataJuggler.Blazor.FileUpload
6. Create a SignUp Component to allow new artists to join, including uploading a profile picture
7. Create a Login Component to login existing users with option to store email address and password
8. Create an Artist List Viewer component
9. Create an Image List Viewer component
10. Create an Image Button component to display and select images
11. Load and display images for an artist when selected
12. Display a larger image when selected by changing the Scale property
13. Use BlazorStyled to dynamically change CSS values
14. Use paging to display artists 1 - 5, 6 - 10, etc.
I built this project because I wanted to make sure I could build a real world application, before I started charging a client I wanted to find out what I can and cannot do.
I left out a few things that I may cover in a future tutorial, such as:
1. Forgot Password / Recovery Email
2. I didn't add paging to the Gallery; I capped it at 15 images per artist for now
3. Possibly a shopping cart and / or download image functionality
4. I didn't create any way to delete an image yet.
5. Edit Profile / Change Profile Picture
All these things will make a good Part II, but I wanted to keep version 1 simple.
What you will need:
Visual Studio Version 16.4 or higher. I am using 16.4.5 SQL Server / Express Newer the better. I am using SQL Server Express 2017
Hopefully you are familiar with C# and SQL, but if not you are in the right place to learn.
Here is a sample of the tutorial we are building:
If you want to clone the working version, it is available here:
You will still need to setup up the SQL Server Database, scroll down for Part II.
Part I: Create a new Blazor Project
Step 1: Open Visual Studio and click 'Create New Project
Step 2: Select Blazor App and click Next.
Step 3: Configure Your Project details and click the Create button.
Step 4: Leave everything as is. ASP.NET Core 3.0 and Blazor Server App will already be selected.
Click Create.
As the note on the screen shot mentions, we have to leave it as ASP.NET Core 3.0 or Visual Studio creates a class library for some reason.
Step 5: After your project is created, expand the data folder and delete the two files:
Step 6: Build your project and you will encounter four errors:
Expand the Pages folder, and select the files FetchData.razor & Counter.razor
Right Click > Select Delete.
Next, double click on Startup.cs to open it.
Remove line 12:
using BlazorImageGallery.Data;
Remove line 30:
services.AddSingleton<WeatherForecastService>();
Build your project again and it should compile.
Step 7: Delete NavMenu.razor
Step 8: Right click the BlazorImageGallery project and select Properties.
In project Properties, change the Target Framework to Dot Net Core 3.1
Right click on the tab Blazor Image Gallery > Select Close to close Project Properties.
This concludes part 1.
Part II: Create SQL Database & DataTier
In SQL Server Management Studio create a new database named BlazorImageGallery.
Execute the following SQL Script to create the tables and stored procedures:
Click the View Raw button at the bottom of the SQL, then click Control + A to select all followed by Control + C to copy to your clipboard.
In SQL Server Management Studio click the New Query button, and paste in the copied text.
Click the execute button to create the tables and stored procedures.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Data Source=[ServerName];Initial Catalog=BlazorImageGallery;Integrated Security=True
SQL Authentication
Data Source=[ServerName];Initial Catalog=BlazorImageGallery;Integrated Security=False;User ID=[UserName];Password=[Password]
Create System Environment Variable
In the Windows 10 search box, start type Edit System Environment Variables
Click the Edit System Environment Variables button.
In the System Environment Variables section at the bottom, click 'New'.
Environment Variable Properties
Name: BlazorImageGallery
Value: (Paste In Your Connection String)
This concludes part 2.
Part III: Complete Web Project
In the final step we are to complete the following tasks:
1. Modify MainLayout.razor
2. Add Nuget packages
3. Download wwwroot content and copy to web folder
4. Create Components Or Download Components.zip
5. Modify Index Page
6. Modify Startup.cs
7. Modify Imports.razor
8. Create GalleryManager class
9. Create Models
10. Download Images for Gallery
11. Run Program / Create Artists / Galleries
12. Test everything works
Modify MainLayout.razor
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Download the wwwrootcontent.zip file, save and extract it to a temp folder.
Copy and replace site.css with the existing file wwwroot/css/site.css.
Copy and replace favicon.ico with the existing favicon.css
Copy the Images folder to below the wwwroot folder.
The end result should look like this:
Create Components
Originally I planned creating ten files and pasting in the code for each, but to save a lot of time I created a zip file of the components. Create a new folder named Components and then download extract the contents to a temp folder. Paste the extracted files into the new Components directory. Visual Studio automatically includes the files in the project.
Expand the Pages folder and double click on the Index.razor.
Index.razor
Hit Control + A to select all followed by the backspace to erase the existing code.
Select the Pages folder, and create a new class named Index.razor.cs.
Hit Control + A to select all followed by the backspace to erase the existing code.
Paste in the following code to the corresponding file for Index.razor & Index.razor.cs:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add these two lines to the ConfigureServices method, below AddServerSideBlazor().
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add these four lines to the bottom of the existing import statements:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Create a new folder named Util at the same level as wwwroot, Pages, etc.
Create a new class named GalleryManager.cs and replace out the existing code with:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Create a new folder named Models at the same level as wwwroot, Pages, etc.
In the Models folder, create the following two files, and replace out the text for each.
LoginModel.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
We need to create two folders under wwwroot/Images
1. Artists
2. Gallery
Modify _Host.cshtml File
Under the pages folder, make the following changes to _Host.cshtml:
1. Change the title on line 10 to Blazor Image Gallery Sample
2. Paste the following 3 lines to directly above the closing </head> tag.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Paste these two lines directly above the link to Blazor.Server.js (line 22 and 23 after the paste)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
* The code above is part of the open source project and Nuget package: DataJuggler.Blazor.Components, a work in progress.
In the diagram for the sample project below, the Index page contains a component named Login, and the Login component has a child component named SignUp.
The Login component has an EventCallback parameter:
In this scenario I am building a sample called Blazor Image Gallery where artists can sign up and upload images for their own portfolio as part of the Gallery. My database contains an Artist table and when a user signs up or logs in, I needed a way to inform the Index page that a user (an Artist) has signed in. One option is to set a Parameter on the Index page for Artist ID or I could use the Preview Nuget package Microsoft.AspNetCore.ProtectedBrowserStorage, which this project already uses to store the users email address and password hash if a user chooses to be remembered. I didn't like either of these options because I still needed a way to send messages to the parent component or page. Interfaces Interfaces make communication between a parent page or component and child very simple. In this example my Index page and Login component both implement IBlazorComponentParent and the Login and SignUp components both implement IBlazorComponent.
Both the IBlazorComponent and IBlazorComponentParent interfaces have a ReceiveData method:
In the image below, the Login component implements IBlazorComponentParent interface, so setting the parent is as simple as Parent = "this":
The SignUp component implements IBlazorComponent, and your setter for the Parent property needs to look something like this:
In the above setter, the HasParent property is a simple test for (Parent != null). If the Parent exists, the SignUp component registers itself with the parent Login component. Registering Components Objects that implement IBlazorComponentParent must contain a Register method. The Register method will be called the first time the Parent property is set. This usually occurs when a component is rendered for the first time. IBlazorComponentParent objects contain a property named Childrenthat you may instantiate to store child components as they register. You can also store component instances as a property, as shown here the Login component is expecting the SignUp component to register.
In the picture above, NullHelper is part of DataJuggler.UltimateHelper.Core Nuget package, and it a shortcut for (component != null) && (Children != null). Once both objects are verified to exist, the component is added to the Children collection. Sending Messages A message object is a class that contains a few properties to make it easy to send information between components. Message Objects Text - A string property for any text information you want to send. For more complex data, I created an object called a NamedParameter. NamedParameter Properties: Name - An identifier so parameters can be set to distinguish items Value - An object value that can contain any type of data. Each message contains a Parameters collection that is created when you call the constructor for a Message. At some point a MessageHelper class will be created to simplify this, but for now create your NamedParameter instances and add them to your message. In the example shown below, the SignUp component is notifying the Login component that an Artist has signed up:
In the Login component I receive the message, then I call the OnLogin EventCallback which notifies the Index page.
The Index page then receives the LoginResponse object, which I get the Artist from and store in memory:
After login, my UI is updated and the Login Component changes:
The Blazor Image Gallery is almost finished, I just wanted to write this blog post as I think interfaces are the easiest way I have found for communicating between parent and child. Let me know your thoughts or if you know of a better way to communicate between components. Thanks for reading. Please visit my YouTube channel and subscribe as I make new videos as often as I can.