LukeMauiMarkup Library 개발기

지원 net8.0부터 지원합니다.

1.LukeMauiMarkup Nuget 설치


참고) 설치 시 CommunityToolkit.Mvvm, Markup 최신버전이 같이 되기 설치되기 때문에 별도로 설치할 필요없습니다.

2. MauiProgram BuilderUse 처리

3. MainPage에서의 RootPage 생성


참고) 단일 페이지를 만들 경우엔 MainPage = new MainPage()로 할 것

4. MainPage의 상속클래스는 LukeContentPage로 변경

추상멤버 추가 구현


빌드 함수쪽은 핫리로드 되는 시점에 그리고자 하는 컨트롤을 넣습니다.

12개의 좋아요

Global Using 클래스 파일 추가하면
using도 줄일 수 있고 Grid 관련 Columns.Define, Rows.Define 처리할 때 인테리센스를 이용할 수 있으니
매번 사용하는 Using은 미리 등록하시는걸 추천드립니다.

// MVVM Toolkit
// .NET MAUI Markup
global using LukeMauiMarkup;
global using LukeMauiMarkup.Exentions;
global using CommunityToolkit.Maui.Markup;
global using CommunityToolkit.Mvvm.ComponentModel;
global using CommunityToolkit.Mvvm.Input;
// Static
global using static CommunityToolkit.Maui.Markup.GridRowsColumns;
global using static Microsoft.Maui.Graphics.Colors;
global using MC = Microsoft.Maui.Controls;
6개의 좋아요

Maui에서는
HexString값으로 색상을 표현하고자 할 땐

#9da2e8” 을 기입해줘야합니다.
#을 뺄 경우엔 오류로 예외 처리가 되지 않아서 앱 크래쉬 앱이 종료가 됩니다.

기존 방식
image

변경 방식
image

아래와 같이 Extentions 클래스를 관리함으로 써 부모상속이 컨트롤, 페이지에서도 가져다 쓸 수 있게
추가할 예정입니다.

4개의 좋아요

1.0.0.3 적용 완료

3개의 좋아요

에뮬레이터에서는 종종 hotReload가 동작되지 않거나 크랙되는 이슈가 있어서

임시로 Window로 개발을 하고 있습니다.

호갱노노 앱 만들어보면서
현재 추가 기능이 있는지 탐색 중입니다. :dark_sunglasses:

프로젝트소스는

7개의 좋아요

Border에 대한 값은 선언형이 아니더군요…
그래서 확장메서드로 만들어보았습니다.

현재 Maui.Markup에선…
image

변경
image

다른 코드임을 확인하기 위해 아래와같이 테스트 코드로 작성하였습니다.

테스트 코드
image

동작 이미지
image

버전 1.0.0.5 이후부터 구현할수있도록 업데이트 예정입니다!

5개의 좋아요

Popup 화면 개발

위 화면 작업하기 위해서 여러 고민을 끝에 라이브러리(Plugin.Maui.Popup)를 포함하여 팝업페이지 클래스를 만들기로 결정하였습니다.


(LukeContentPage와 똑같았기 떄문에 향후엔 별도로 공통 클래스로 뽑아 처리하면 깔끔하게 구현 예정)

NavigattionPage의 PushModal HotReload 기능 이슈(해결완료)

NavigatePage의 경우 Push와 PushModal에 있어서 HotReload 구현 방식이 달랐습니다.

현재 네비게이션의 CurrentPage의 경우 동작되는 구간입니다.
Push 페이지를 띄울 경우에는 정상적으로 동작이 되지만,
PushModal 페이지를 띄울 경우 CurrentPage는 PushModal을 띄운 페이지를 뜻하고 있다는 것을 확인하였습니다.


위와 같이 TryGetModalStackPage함수(기존 HotReload 예제) 를 응용하여 ModalStack의 마지막 페이지를 불러와서 Build함수 실행하는 것으로 해결하였습니다.






Screenshot 2023-12-01 at 10.43.08


알게된 점

WPF와 MAUI는 비슷하다!?

@jamesnet214 님께서 항상 말씀하신 CustomControl(사용자지정컨트롤)의 중요성에 깊이 공감하고 있기 때문에 자연스럽게 Maui와 접점 부분이 있는지 조금이나마 관심유지하며 지켜보고 있었습니다.

그러다 이번 Slog를 통해 Popup 라이브러리 소스 분석 중 WPF와 비슷한점을 발견하였습니다.
Maui에서 WPF의 각 컨트롤마다 속성을 지우고 다시 그릴 수 있는 Template 이 없는 줄 알았는데
ControlTemplate이 그 기능을 하고 대체하고 있다는 것을 알게 되었습니다.
ControlTemplate는 ContentPage와 ContentView 존재하였습니다.

즉,

WPF의 Window = Maui의 ContentPage
WPF의 ContentControl or UserControl = Maui의 ContentView

하지만 아쉽게도.. Maui에서 ContentPage와 ContentView, 특정컨트롤(RadioButton) 외 다른 컨트롤에서는 ControlTemplate들이 존재하지 않았습니다.

ControlTemplate은 Page와 Layout의 고유 BindableProperty로 존재하는 반면
다른 컨트롤은 특별하지 않는 이상 상위계층이 전부 View로 상속받고 있기 때문입니다.
하지만 위에서 언급한 특정컨트롤 인 RadioButton은 ControlView와 같은 Layout을 상속받고 있는것을 보았습니다.
RadioButton는 커스텀을 통해 만들어진 컨트롤이라는 것을 알게 되었습니다.

(점점 파고들다보니 내용이 길어질 거 같아 다음 기회에 다른 게시글을 통해..공유하는것으로하겠습니다.)

(추측) 팝업창으로 만들어진 ContentPage는 왜 변경되지 않을까?

대게 라이브러리로 만들어진 Popup은 호출 시 PushModal 방식으로 Page를 띄웁니다.

제가 HotReload 구현했을 때 이슈와 비슷한 상황으로 PushModal의 경우 띄어진 ContentPage는 NavigationPage의 CurrentPage에 해당되지 않기 때문에 HotReload가 동작되지 않는것으로 파악됩니다.

(왠지 이거 Maui Github에 버그이슈로 올리면 해결이 가능할거 같은..)

8개의 좋아요

멋진 슬로그 입니다!

5개의 좋아요

감사합니다! 힘이나네요! :fire: :fire: :fire:

5개의 좋아요

Q : Markup에서의 공통 컨트롤의 경우 컨트롤 클래스 묶어서 처리할 수 있을까?

image
바로 이 화면을 보고
‘공통 컨트롤로 묶어서 처리해야지~’ 라는 생각으로
몇 일간에 고민과 테스트를 통해 내린 결론은


할 수 도 있고, 못할 수 도 있고? 입니다.
차이는 HotReload를 쓰고 안쓰고의 차이였기 때문에 내린 결론이였습니다.


현재 제가 개발하고 있는 LukeMauiMarkup의 경우도 그렇고 현재 Community.Maui.Markup에서의 샘플에서도 동일한 답일 수 있을 것 같습니다.

image
위의 함수는 모든 클래스에서의 변화를 HotReload를 통해서 알려주고 있는데요.

image

해당 클래스의 변화는 감지합니다만 딱 감지까지입니다.
Grid로도 상속해보았고, ContentView로도 상속해보았습니다.
Page라는 상속이 된 경우에만 화면을 다시 그려줍니다.

Page 내 Content 영역에 대한 부분에서만 실시간으로 변경이 가능하고 그 외적으로
완전히 불변의 값인 경우에는 클래스에 고유값으로 처리할 수 있습니다.

image

4개의 좋아요

개발의 대세를 따르기 위해…
image
image

3개의 좋아요

현재 작업

Screenshot 2023-12-05 at 22.55.19

Entry - Maui.FreakyControl 中 FreakyTextInputLayout

4개의 좋아요

버튼의 아이콘을 추가

image

4개의 좋아요


최근 본 영상들 중 여러 영상들이 있는데 그 중 감명깊게 본 영상 입니다.

요약 : 서비스가 커지면 커질수록 페이지들은 많아지기 때문에
연계성을 찾기 어려워 관리할 수 있도록 하는 방법에 대한 내용


위 방법을 제 토이프로젝트에 적용을 해보았습니다.
아래와 같이 Signup 단계 (2개의 페이지)를 구성해보았습니다.
Screenshot 2023-12-12 at 14.04.08


SinupService

  • Sinup에 필요한 페이지의 구성과 각 페이지 별로 작성되는 데이터들을 관리합니다.
  • Next 함수 호출 할 때마다 등록 된 페이지들을 단계별로 Navigation 처리됩니다.

PageContainer

  • 페이지(뷰)와 뷰모델을 하나의 클래스에서 관리할 목적이며, 생성과 동시에 페이지에 뷰모델을 연결해주는 작업을 처리하는 영역입니다.
4개의 좋아요

오늘 아침 xamarin 단톡방에서
@honeyhead 님께서 아이디어를 제공해주셨는데

‘C#12 컬렉션 표현식을 응용해서 컨트롤을 추가해보면 어떨까?’ 라는
생각에서 진행해보았습니다.

컬렉션 표현식 적용 전
image

컬렉션 표현식 적용 후
image

Layout 중 유일하게 제 멋대로 만들어서 가지고 놀 수 있는
HStack과 VStack에 시험 삼아 만들어 배포해볼 예정입니다.

p.s 다른 Layout을 상속된 컨트롤은 고민을 좀 더 해봐야할 거같네요…:frowning:

7개의 좋아요

오랜만에 다시 한번 라이브러리 뚝딱뚝딱 거렸습니다.

변경사항

  • 매개변수 params을 활용한 선언형방식(Content, Children, ColumnsDefinitions, RowDefinitions)
  • LukeMauiMarkup Template Nuget 반영

매개변수 params을 활용한 선언형방식
// 기존코드

public override void Build()
{
    Content = new Grid()
    {
       RowDefinitions = Rows.Define(Auto, Star)
        Children =
        {
            new Label()
              .Row(0)
              .Text("Welcome to .NET MAUI!!!"),

            new Label()
              .Row(1)
              .Text("Welcome to .NET MAUI!!!")
        }
    }
    .BackgroundColor(Colors.Red);
}

// 개선코드

public override void Build() 
{
   this.Content(
       new Grid()
          .RowDefinitions (Auto, Star)
          .Children(
               new Label()
                   .Row(0)
                   .Text("Welcome to .NET MAUI!!!"),

               new Label()
                   .Row(1)
                   .Text("Welcome to .NET MAUI!!!")
             )
   )
    .BackgroundColor(Colors.Red);
}

LukeMauiMarkup Template Nuget 반영
설치방법

dotnet new install LukeMauiMarkup.Templates::1.0.0

Nuget

템플릿의 경우는 남을 위해서보단 저만의 템플릿을 만들고 언제어디서든 다운받을 목적을 만들어보았습니다.

8개의 좋아요