콘텐츠로 건너뛰기
» Posts » [Blazor] Mudblazor의 List를 활용한 Treeview로 DB바인딩

[Blazor] Mudblazor의 List를 활용한 Treeview로 DB바인딩

C#을 공부하면서 웹페이지를 만들고 싶어졌다.

근데 ASP.NET CORE로 웹페이지를 C#과 연동해서 매우 쉽게 만들 수 있다는걸 알게되었다.

새로운 언어를 배울 필요도 없이 바로 웹페이지를 만들 수 있다니..!

C#을 사용해서 Razor라고 하는 웹페이지 템플릿을 이용하면 된다.

<출처 : ASP.NET이란? | .NET (microsoft.com)>
ASP.NET에 대해 간단히 소개 하자면,
ASP.NET은 .NET을 사용하여 최신 웹앱 및 서비스를 빌드하기 위해 Microsoft에서 만든 오픈 소스 웹 프레임워크
ASP.NET은 플랫폼 간이며 Windows, Linux, macOS, and Docker에서 실행됩니다.
자세한건 공식 문서 참조

아무튼, Blazor를 활용해서 웹페이지를 구축중인데 Mudblazor라는 무료 라이브러리를 사용중이다.

DB를 나열하고 다운받기에는 Treeview 구조가 가장 친숙할듯 하여 MudList를 이용해서 만들어 보려고 한다.

좌측에는 Treeview를 만들고 우측에는 Table을 가지는 윈도우 탐색기 같은 형태로 구상중이다.

Dropzone의 Mailbox 예제를 활용했다.

@using Microsoft.AspNetCore.Components

<MudDropContainer T="DropItem" Items="_items" ItemsSelector="@((item,dropzone) => item.Identifier == dropzone)" ItemDropped="ItemUpdated">
    <ChildContent>
        <MudPaper MinHeight="500px" Class="d-flex flex-1">
            <MudList Clickable="true" Dense="true" @bind-SelectedValue="_selectedFolder">
                <MudListSubheader>MailBox</MudListSubheader>
                <MudDropZone T="DropItem" Identifier="Inbox" OnlyZone="true">
                    <MudListItem Text="Inbox" Value="@("Inbox")" Icon="@Icons.Material.Filled.Inbox"/>
                </MudDropZone>
                <MudDropZone T="DropItem" Identifier="Sent" OnlyZone="true">
                    <MudListItem Text="Sent" Value="@("Sent")" Icon="@Icons.Material.Filled.Send"/>
                </MudDropZone>
                <MudDropZone T="DropItem" Identifier="Drafts" OnlyZone="true">
                    <MudListItem Text="Drafts" Value="@("Drafts")" Icon="@Icons.Material.Filled.Drafts"/>
                </MudDropZone>
                <MudListItem Icon="@Icons.Material.Filled.Label" Text="Categories" InitiallyExpanded="true">
                    <NestedList>
                        <MudDropZone T="DropItem" Identifier="Social" OnlyZone="true">
                            <MudListItem Dense="true" Text="Social" Value="@("Social")" Icon="@Icons.Material.Filled.Group" Class="pl-8"/>
                        </MudDropZone>
                        <MudDropZone T="DropItem" Identifier="Forums" OnlyZone="true">
                            <MudListItem Dense="true" Text="Forums" Value="@("Forums")" Icon="@Icons.Material.Filled.Forum" Class="pl-8"/>
                        </MudDropZone>
                    </NestedList>
                </MudListItem>
            </MudList>
            <MudDivider Vertical="true" FlexItem="true" />
            <MudList Dense="true" Clickable="true" Class="d-flex flex-column flex-grow-1 py-0">
                <MudToolBar DisableGutters="true" Dense="true">
                    <MudCheckBox @bind-Checked="@ToolbarCheckBox"/>
                    <MudIconButton Icon="@Icons.Material.Filled.Refresh"/>
                    <MudIconButton Icon="@Icons.Material.Filled.MoreVert"/>
                    <MudSpacer/>
                    <MudIconButton Icon="@Icons.Material.Filled.ChevronLeft"/>
                    <MudIconButton Icon="@Icons.Material.Filled.ChevronRight"/>
                </MudToolBar>
                <MudDivider/>
                <MudDropZone T="DropItem" Identifier="@_selectedFolder.ToString()" Class="flex-grow-1"/>
            </MudList>
        </MudPaper>
    </ChildContent>
    <ItemRenderer>
        <MudListItem Text="@context.Name"/>
        <MudDivider/>
    </ItemRenderer>
</MudDropContainer>

@code {
    public bool ToolbarCheckBox { get; set; } = false;
    object _selectedFolder = "Inbox";
    
    private void ItemUpdated(MudItemDropInfo<DropItem> dropItem)
    {
        dropItem.Item.Identifier = dropItem.DropzoneIdentifier;
    }
    
    private List<DropItem> _items = new()
    {
        new DropItem(){ Name = "Your exchange rate and Klarna benefits here", Identifier = "Inbox" },
        new DropItem(){ Name = "IKEA - Betalningsbekräftelse för din order", Identifier = "Inbox" },
        new DropItem(){ Name = "Leverans beställd till dig​", Identifier = "Inbox" },
        new DropItem(){ Name = "You’ve Got Sales! Cotton Bureau On Demand Report for Thursday, February 24, 2022", Identifier = "Inbox" },
        new DropItem(){ Name = "Answer: Offer to buy mudblazor", Identifier = "Drafts" },
        new DropItem(){ Name = "Inloggningsvarning för Facebook Messenger for Android", Identifier = "Social" },
        new DropItem(){ Name = "Nya privata meddelanden på SweClockers", Identifier = "Forums" },
    };
    
    public class DropItem
    {
        public string Name { get; init; }
        public string Identifier { get; set; }
    }
}

어차피 Dropzone은 안쓸거니까 날리고 나면 별거 없다.

나는 DB를 2번정도만 분류 하면 될 것 같아서 2중 for문을 사용했지만 분류해야할 항목이 너무 많지만 않다면 다중 for문으로 늘려도 될 듯 하다.

<MudPaper MinHeight="500px" Class="d-flex flex-1">
    <MudList  Clickable="true" Dense="true" Color="Color.Primary" @bind-SelectedValue="_selectedFolder">
        <MudListSubheader>
            Item List
        </MudListSubheader>
        @* 폴더명을 1차로 나누고 NestedList를 2차로 나누는 2중 for문 사용*@
        @foreach (var first in GetFirst())
        {
            <MudListItem Icon="@Icons.Material.Filled.Folder" Text="@first" InitiallyExpanded="false">
                <NestedList>
                    @foreach (var second in GetSecond(first))
                    {
                        <MudListItem Icon="@Icons.Material.Filled.Folder" Text="@second" OnClick="() => OnFolderClick(first, second)" />
                    }
                </NestedList>
            </MudListItem>
        }
    </MudList>
    @*세로 형태로 나누는 Divider*@
    <MudDivider Vertical="true" FlexItem="true" />
    <MudList Dense="true" Clickable="true" Class="d-flex flex-column flex-grow-1 py-0">
            @*Toolbar로 상단 기능 추가*@
        <MudToolBar DisableGutters="true" Dense="true">
            <MudIconButton Icon="@Icons.Material.Filled.Refresh" OnClick="@ItemRefreshBtn" />
            <MudIconButton Icon="@Icons.Material.Filled.MoreVert" />
            <MudSpacer />
            <MudButton Variant="Variant.Filled" Color="Color.Error" OnClick="@Toggle">Close</MudButton> @*종료 버튼*@
        </MudToolBar>
        <MudDivider />

        @*TODO : TABLE 들어가면 됨*@

    </MudList>
</MudPaper>




@code{

List<FirstItems> firstObjList ;  // firstObjList 객체의 리스트
List<SecondItems> secondObjList ;  // secondObjList 객체의 리스트

    private IEnumerable<string> GetFirst()
    {
        return firstObjList.Where(x => x.CATEGORY == "Your_string") // 카테고리가 Your_string 해당하는 NAME 출력
                        .Select(c => c.NAME)
                        .Distinct();
    }
    

    private IEnumerable<string> GetSecond(string parent)
    {
        return secondObjList.Where(c => c.SECOND_CATEGORY == parent)
                        .Select(c => c.SECOND_NAME)
                        .Distinct(); 
    }
}

 

Table 부분은 아래와 같이 하면 된다.

구조는 역시 서버에 분류되어 있는 그룹을 클릭하면 table로 출력하도록 되어있음.

시각적으로 편하게 하기 위해 파일 탐색기 처럼 폴더로 나눈것 처럼 만들었다.

@*선택한 폴더 별로 TABLE값이 다르게 설정*@
 <MudTable Items="@GetFilteredItems()" Dense="true" Hover="true" Bordered="true" SortLabel="Sort By"
           FixedHeader="true" Height="32vh">
     <ToolBarContent>
     </ToolBarContent>
     <HeaderContent>
         <MudTh>ID(KEY)</MudTh>
         <MudTh>Name</MudTh>
         <MudTh>UserID</MudTh>
         <MudTh>Delete</MudTh>
     </HeaderContent>
     <RowTemplate>
         <MudTd DataLabel="ID">@context.ID</MudTd>
             <MudTd DataLabel="NAME">@context.NAME</MudTd>
             <MudTd DataLabel="USERID">@context.USERID</MudTd>
             @*TODO : 삭제 버튼 기능 만들기*@
             <MudTd DataLabel="DELETE">
                 <MudIconButton Variant="Variant.Filled" Icon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="@Toggle"></MudIconButton>
             </MudTd>
             <MudTd>
             </MudTd>
         </RowTemplate>
         <NoRecordsContent>
             <MudText>No matching records found</MudText>
         </NoRecordsContent>
         <LoadingContent>
             <MudText>Loading...</MudText>
         </LoadingContent>
         <PagerContent>
             <MudTablePager PageSizeOptions="new int[]{25, 50, 100}" />
         </PagerContent>
     </MudTable>


@code {
    List<ThirdItems> thirdObjList; // thirdObjList 객체의 리스트
    private string _selectedFolder;
    private string _selectedSubFolder;

    // [Load] 폴더 선택
    private void OnFolderClick(string folder, string subFolder)
    {
        _selectedFolder = folder;
        _selectedSubFolder = subFolder;
        StateHasChanged(); // UI를 강제로 리프레시합니다.
    }

 private IEnumerable<ThirdItems> GetFilteredItems()
 {
     return thirdObjList.Where(c => c.Class맴버A == _selectedFolder && c.Class맴버B == _selectedSubFolder);
 }

}

 

DB내에서 삭제 또는 미노출 버튼은 아직 안만들었는데 

만들면 다시 업데이트 할 예정이다.

 

 

 

 

조금 사용해보니 정말 유저친화적으로 만들어졌다고 느껴진다.

가장 큰 장점은 C#을 그대로 활용할 수 있다는점 ! 

물론 단점도 있지만 아직까진 대만족 중