Blazor Proje Yapısı ve Genel Mantığı

Blazor Proje Yapısı ve Genel Mantığı

Blazor, C# ve .NET kullanarak interaktif web uygulamaları oluşturmamızı sağlayan bir framework'tür. İki ana modeli vardır: Blazor Server ve Blazor WebAssembly.

1. Temel Proje Yapısı

Blazor Server Proje Yapısı:

MyBlazorApp/
├── Pages/
│   ├── Index.razor
│   ├── Counter.razor
│   └── FetchData.razor
├── Shared/
│   ├── MainLayout.razor
│   └── NavMenu.razor
├── wwwroot/
│   └── css/
├── App.razor
├── Program.cs
└── appsettings.json

 

Blazor WebAssembly Proje Yapısı:

MyBlazorApp.Client/
├── Pages/
├── Shared/
├── wwwroot/
├── Program.cs
└── Properties/

 

2. Temel Bileşenler (Components)

Basit Bir Bileşen Örneği:

@page "/counter"

Counter

Current count: @currentCount

Click me@code { private int currentCount = 0; private void IncrementCount() { currentCount++; } }

 

Parametre Alan Bileşen:

@page "/user"

<h3>User Information</h3>

<UserProfile Name="@userName" Age="25" />

@code {
    private string userName = "Ahmet Yılmaz";
}
<!-- UserProfile.razor -->
<div class="user-card">
    <h4>@Name</h4>
    <p>Age: @Age</p>
    <p>@Description</p>
</div>

@code {
    [Parameter]
    public string Name { get; set; }

    [Parameter]
    public int Age { get; set; }

    [Parameter]
    public string Description { get; set; } = "No description provided";
}

3. Data Binding (Veri Bağlama)

Two-Way Data Binding:

 

@page "/form"

<h3>User Form</h3>

<input @bind="Name" @bind:event="oninput" />
<p>Hello, @Name!</p>

<input type="number" @bind="Age" @bind:format="yyyy-MM-dd" />
<p>Age: @Age</p>

<button @onclick="SubmitForm">Submit</button>

@code {
    private string Name { get; set; } = "";
    private int Age { get; set; } = 0;

    private void SubmitForm()
    {
        Console.WriteLine($"Name: {Name}, Age: {Age}");
    }
}

 

4. Olay Yönetimi (Event Handling)

@page "/events"

<h3>Event Examples</h3>

<input value="@text" @oninput="HandleInput" />
<button @onclick="HandleClick" 
        @onclick:preventDefault="true">Click Me</button>

<select @onchange="HandleSelectChange">
    <option value="1">Option 1</option>
    <option value="2">Option 2</option>
</select>

@code {
    private string text = "";

    private void HandleInput(ChangeEventArgs e)
    {
        text = e.Value?.ToString() ?? "";
        Console.WriteLine($"Input changed: {text}");
    }

    private void HandleClick()
    {
        Console.WriteLine("Button clicked!");
    }

    private void HandleSelectChange(ChangeEventArgs e)
    {
        Console.WriteLine($"Selected: {e.Value}");
    }
}

 

5. Koşullu Render ve Listeler

@page "/todo"

<h3>Todo List (@todos.Count(t => !t.IsDone))</h3>

<input @bind="newTodo" placeholder="Add new todo" />
<button @onclick="AddTodo">Add</button>

@if (todos.Any())
{
    <ul>
        @foreach (var todo in todos)
        {
            <li>
                <input type="checkbox" @bind="todo.IsDone" />
                <span style="@(todo.IsDone ? "text-decoration: line-through" : "")">
                    @todo.Title
                </span>
                <button @onclick="() => RemoveTodo(todo)">Remove</button>
            </li>
        }
    </ul>
}
else
{
    <p>No todos yet!</p>
}

@code {
    private List<TodoItem> todos = new();
    private string newTodo = "";

    private void AddTodo()
    {
        if (!string.IsNullOrWhiteSpace(newTodo))
        {
            todos.Add(new TodoItem { Title = newTodo });
            newTodo = "";
        }
    }

    private void RemoveTodo(TodoItem todo)
    {
        todos.Remove(todo);
    }

    class TodoItem
    {
        public string Title { get; set; } = "";
        public bool IsDone { get; set; }
    }
}

6. Lifecycle Metodları

@page "/lifecycle"
@implements IDisposable

<h3>Component Lifecycle</h3>
<p>Render Count: @renderCount</p>
<p>Data: @data</p>

@code {
    private int renderCount = 0;
    private string data = "";
    private Timer timer;

    protected override void OnInitialized()
    {
        Console.WriteLine("Component initialized");
        data = "Initial data";
    }

    protected override async Task OnInitializedAsync()
    {
        // Async initialization
        await Task.Delay(1000);
        data = "Data loaded asynchronously";
    }

    protected override void OnParametersSet()
    {
        Console.WriteLine("Parameters set");
    }

    protected override async Task OnParametersSetAsync()
    {
        await base.OnParametersSetAsync();
    }

    protected override void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            Console.WriteLine("First render completed");
            timer = new Timer(_ => InvokeAsync(StateHasChanged), null, 1000, 1000);
        }
        renderCount++;
    }

    public void Dispose()
    {
        timer?.Dispose();
        Console.WriteLine("Component disposed");
    }
}

 

7. Servis Kullanımı ve Dependency Injection

Servis Tanımı:

// Services/IDataService.cs
public interface IDataService
{
    Task<List<string>> GetItemsAsync();
    Task AddItemAsync(string item);
}

// Services/DataService.cs
public class DataService : IDataService
{
    private List<string> items = new() { "Item 1", "Item 2", "Item 3" };

    public Task<List<string>> GetItemsAsync()
    {
        return Task.FromResult(items);
    }

    public Task AddItemAsync(string item)
    {
        items.Add(item);
        return Task.CompletedTask;
    }
}

 

Servis Kaydı (Program.cs):

// Blazor Server için
builder.Services.AddScoped<IDataService, DataService>();

// Blazor WebAssembly için
builder.Services.AddSingleton<IDataService, DataService>();

 

Bileşende Servis Kullanımı:

@page "/services"
@inject IDataService DataService

<h3>Service Example</h3>

@if (items == null)
{
    <p>Loading...</p>
}
else
{
    <ul>
        @foreach (var item in items)
        {
            <li>@item</li>
        }
    </ul>
}

<input @bind="newItem" />
<button @onclick="AddItem">Add Item</button>

@code {
    private List<string> items;
    private string newItem = "";

    protected override async Task OnInitializedAsync()
    {
        items = await DataService.GetItemsAsync();
    }

    private async Task AddItem()
    {
        if (!string.IsNullOrWhiteSpace(newItem))
        {
            await DataService.AddItemAsync(newItem);
            items = await DataService.GetItemsAsync();
            newItem = "";
        }
    }
}

 

8. Navigation (Yönlendirme)

@page "/navigation"
@inject NavigationManager Navigation

<h3>Navigation Examples</h3>

<button @onclick="GoToCounter">Go to Counter</button>
<button @onclick="GoToExternal">Go to External Site</button>

<button @onclick="NavigateWithParameters">Navigate with Parameters</button>

@code {
    private void GoToCounter()
    {
        Navigation.NavigateTo("/counter");
    }

    private void GoToExternal()
    {
        Navigation.NavigateTo("https://www.microsoft.com", true);
    }

    private void NavigateWithParameters()
    {
        Navigation.NavigateTo($"/user?name=Ahmet&age=30");
    }
}

 

9. Layout ve Routing

Main Layout (MainLayout.razor):

@inherits LayoutView

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>

 

Route Parameters:

@page "/user/{Id:int}"

<h3>User Details</h3>
<p>User ID: @Id</p>

@code {
    [Parameter]
    public int Id { get; set; }

    protected override void OnParametersSet()
    {
        // Id parametresini kullanarak veri çekme işlemleri
    }
}

10. State Management

Basit State Yönetimi:

@page "/state"
@inject IJSRuntime JSRuntime

<h3>State Management</h3>

<button @onclick="IncrementCount">Count: @currentCount</button>
<button @onclick="SaveState">Save State</button>
<button @onclick="LoadState">Load State</button>

@code {
    private int currentCount = 0;

    private void IncrementCount()
    {
        currentCount++;
    }

    private async Task SaveState()
    {
        await JSRuntime.InvokeVoidAsync("localStorage.setItem", "count", currentCount);
    }

    private async Task LoadState()
    {
        var savedCount = await JSRuntime.InvokeAsync<string>("localStorage.getItem", "count");
        if (int.TryParse(savedCount, out int count))
        {
            currentCount = count;
        }
    }
}

 

Önemli Noktalar:

  1. Component-Based: Her şey bileşenlerden oluşur

  2. Razor Syntax: HTML ve C# bir arada kullanılır

  3. Two-Way Binding@bind directive ile kolay veri bağlama

  4. Event Handling@onclick@oninput gibi event'ler

  5. Dependency Injection: Built-in DI container

  6. JavaScript Interop: JS kütüphaneleri ile entegrasyon

  7. Routing: Attribute-based routing

Bu temel yapıları anladıktan sonra, Blazor ile full-stack web uygulamaları geliştirebilirsiniz. Her bileşen kendi state'ini yönetir ve gerektiğinde parent-child ilişkileri ile veri akışı sağlanır.