Visual Studio Item Template

Visual Studio μ—μ„œ μ½”λ“œλ₯Ό μž‘μ„±ν•  λ•Œ, ν”„λ‘œμ νŠΈμ— μƒˆ ν•­λͺ©μ„ μΆ”κ°€ν•˜κ³ , κ΅¬ν˜„μ„ μ‹œμž‘ν•©λ‹ˆλ‹€.

이 λ•Œ, κΉ¨λ—ν•˜κ²Œ λΉ„μ›Œμ Έ μžˆλŠ” μ½”λ“œ 파일이 쒋을 λ•Œλ„ μžˆμ§€λ§Œ, 반볡적으둜 μž‘μ„±ν•˜λŠ” μ½”λ“œκ°€ ν¬ν•¨λ˜λŠ” κ²½μš°λ„ μžˆμŠ΅λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄, Xamarin Forms 둜 λͺ¨λ°”일 μ‘μš©ν”„λ‘œκ·Έλž¨μ„ μž‘μ„±ν•˜λŠ” ν”„λ‘œμ νŠΈλ₯Ό μž‘μ—…μ€‘μΌ λ•Œ, Page 와 ViewModel 을 반볡적으둜 μΆ”κ°€ν•˜κ³ , μž‘μ„±ν•©λ‹ˆλ‹€.

Page의 예 .xaml

<core:AppContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                        xmlns:d="http://xamarin.com/schemas/2014/forms/design"
                        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                        xmlns:local="clr-namespace:Kr.Bbon.Product"
                        xmlns:core="clr-namespace:Kr.Bbon.Core;assembly=Kr.Bbon.Core"
                        xmlns:behaviors="clr-namespace:Kr.Bbon.Core.Behaviors;assembly=Kr.Bbon.Core"
                        xmlns:converter="clr-namespace:Kr.Bbon.Core.Converters;assembly=Kr.Bbon.Core"
                        xmlns:viewmodel="clr-namespace:Kr.Bbon.Product.ViewModels"
                        xmlns:fa="clr-namespace:Kr.Bbon.Styles.FontAwesome;assembly=Kr.Bbon.Styles.FontAwesome"
                        xmlns:buttons="clr-namespace:Syncfusion.XForms.Buttons;assembly=Syncfusion.Buttons.XForms"
                        xmlns:inputLayout="clr-namespace:Syncfusion.XForms.TextInputLayout;assembly=Syncfusion.Core.XForms"
                        mc:Ignorable="d"
                        x:Class="Kr.Bbon.Product.Pages.SignUpPage"
                        x:TypeArguments="viewmodel:SignUpViewModel"
                        Title="{Binding Title}"
                        Shell.NavBarIsVisible="False"
                        NavigationPage.HasNavigationBar="False">
        <ContentPage.Resources>
        <converter:FirstValidationErrorConverter x:Key="firstValidationErrorCoverter" />
        <converter:ValidationResultHasErrorConverter x:Key="validationResultHasErrorConverter" />
    </ContentPage.Resources>
        <ContentPage.Content>
                <!-- 화면을 μž‘μ„± -->
        </ContentPage.Content>
</core:AppContentPage> 

Page μ½”λ“œμ˜ 예 .xaml.cs

using Kr.Bbon;
using Kr.Bbon.Product.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace Kr.Bbon.Product.Pages
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    [Route(RouteUri.SignUp)]
    public partial class SignUpPage : AppContentPage<SignUpViewModel>
    {
        public SignUpPage()
            : base()
        {
            InitializeComponent();
        }
    }
}

ViewModel μ½”λ“œμ˜ 예 .cs

using Kr.Bbon.Core;
using Kr.Bbon.Core.Validations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;

namespace Kr.Bbon.Product.ViewModels
{
    public class SignUpViewModel : ViewModelBase
    {
                public SignUpViewModel() 
                        : base() 
                {
                }
    }
}

μƒˆ νŽ˜μ΄μ§€ μž‘μ—… μˆœμ„œ

  1. 클래슀 νŒŒμΌμ„ μΆ”κ°€ν•©λ‹ˆλ‹€.
  2. ViewModel ν΄λž˜μŠ€μ— λ°˜λ³΅λ˜λŠ” μ½”λ“œλ₯Ό μž‘μ„±ν•©λ‹ˆλ‹€.
  3. μ»¨ν…νŠΈ νŽ˜μ΄μ§€ νŒŒμΌμ„ μΆ”κ°€ν•©λ‹ˆλ‹€.
  4. XML λ„€μž„μŠ€νŽ˜μ΄μŠ€λ₯Ό μΆ”κ°€ν•˜κ³ , ν•„μš”ν•œ λ‚΄μš©μ„ μΆ”κ°€ν•©λ‹ˆλ‹€.
  5. ViewModel 클래슀λ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€.
  6. Page λ₯Ό κ΅¬ν˜„ν•©λ‹ˆλ‹€.

λ°˜λ³΅λ˜λŠ” λ‚΄μš©μ„ μž‘μ„±ν•˜κ³  있으면 맀우 ν”Όκ³€ν•©λ‹ˆλ‹€.

λ³΅μ‚¬ν•˜κ³  λΆ™μ—¬λ„£κΈ°λ₯Ό λ°˜λ³΅ν•˜λŠ” μž‘μ—…

λ°˜λ³΅λ˜λŠ” μž‘μ—…μ„ 쀄이기 μœ„ν•΄ μ•„μ΄ν…œ ν…œν”Œλ¦Ώμ„ λ§Œλ“€μ–΄μ„œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Visual Studio 의 ν”„λ‘œμ νŠΈ λ©”λ‰΄μ—μ„œ ν…œν”Œλ¦Ώ 내보내기가 κ°€λŠ₯ν•©λ‹ˆλ‹€.

vs item template export template

ν…œν”Œλ¦Ώ 내보내기 메뉴λ₯Ό μ‚¬μš©ν•˜λ©΄ λ§ˆλ²•μ‚¬ ν˜•μ‹μœΌλ‘œ ν”„λ‘œμ νŠΈλ₯Ό ν…œν”Œλ¦ΏμœΌλ‘œ λ§Œλ“€ 것인지, ν•­λͺ©μ„ μ•„μ΄ν…œ ν…œν”Œλ¦Ώμ„ λ§Œλ“€ 것인지 선택이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

vs item template export template wizard

μ΄λ ‡κ²Œ μ•„μ΄ν…œ ν…œν”Œλ¦Ώμ„ 내보내면 μ•„μ΄ν…œ ν…œν”Œλ¦Ώ 디렉터리에 .zip 파일이 μΆ”κ°€λ˜μ–΄μ Έ μžˆμŠ΅λ‹ˆλ‹€.

πŸ‘‰ μ•„μ΄ν…œ ν…œν”Œλ¦Ώ λ””λ ‰ν„°λ¦¬λŠ” Visual Studio μ˜΅μ…˜μ—μ„œ 확인할 수 μžˆμ–΄μš”.

Visual Studio μ˜΅μ…˜
Visual Studio μ˜΅μ…˜
vs item template options

.zip νŒŒμΌμ€ μ•„λž˜ ν•­λͺ©μ„ ν¬ν•¨ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

  • __PreviewImage.png

μ•„μ΄ν…œ ν…œν”Œλ¦Ώ λ§ˆλ²•μ‚¬μ—μ„œ μ§€μ •ν•œ 미리보기 이미지 파일

  • __TemplateIocn.png

μ•„μ΄ν…œ ν…œν”Œλ¦Ώ λ§ˆλ²•μ‚¬μ—μ„œ μ§€μ •ν•œ μ•„μ΄μ½˜ 이미지 파일

  • MyTemplate.vstemplate
  • 그리고, μ•„μ΄ν…œ ν…œν”Œλ¦ΏμœΌλ‘œ λ‚΄λ³΄λ‚΄κΈ°ν•œ 파일

πŸ‘‰ .vstemplate 파일의 μ •λ³΄λŠ” 방법: ν•­λͺ© ν…œν”Œλ¦Ώ λ§Œλ“€κΈ° νŽ˜μ΄μ§€μ˜ λ§ν¬λ“€μ—μ„œ 확인할 수 μžˆμ–΄μš”.

MyTemplate.vstemplate 파일

νŽΈμ§‘κΈ°λ‘œ MyTemplate.vstemplate νŒŒμΌμ„ 열어보면 μš”μ†Œ μ΄λ¦„μœΌλ‘œ μ–΄λ–€ λ‚΄μš©μΈμ§€ μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€.

TemplateData μš”μ†Œμ™€ TemplateContent μš”μ†Œλ‘œ κ΅¬μ„±λ˜μ–΄μ Έ μžˆμŠ΅λ‹ˆλ‹€.

TemplateData

ν…œν”Œλ¦Ώ μ •λ³΄μž…λ‹ˆλ‹€.

TemplateContent

μƒˆ ν•­λͺ©μ„ μΆ”κ°€ν•  λ•Œ ν”„λ‘œμ νŠΈμ— 좔가될 νŒŒμΌλ“€μ˜ λͺ©λ‘μž…λ‹ˆλ‹€.

λ‚˜λ§Œμ˜ ν…œν”Œλ¦ΏμœΌλ‘œ λ³€κ²½

μ—¬κΈ°μ„œλŠ” Page 와 ViewModel 을 λ™μ‹œμ— ν¬ν•¨ν•˜λŠ” μ•„μ΄ν…œ ν…œν”Œλ¦Ώμ„ μž‘μ„±ν•˜λŠ” 것을 λͺ©μ μœΌλ‘œ ν•©λ‹ˆλ‹€.

μ œμ•½μ‚¬ν•­:

  • Page 와 ViewModel을 ν”„λ‘œμ νŠΈμ— ν¬ν•¨μ‹œν‚€κΈ° μœ„ν•΄ ν”„λ‘œμ νŠΈ λ£¨νŠΈμ—μ„œ ν•­λͺ©μ„ μΆ”κ°€ν•΄μ•Ό ν•©λ‹ˆλ‹€.

ν…œν”Œλ¦Ώμ—μ„œ μ‚¬μš©λ˜λŠ” ν…œν”Œλ¦Ώ λ§€κ°œλ³€μˆ˜ $rootnamespace$ κ°€ ν˜„μž¬ ν•­λͺ©μ„ μΆ”κ°€ν•˜λŠ” μœ„μΉ˜λ₯Ό μ°Έμ‘°ν•©λ‹ˆλ‹€.

  • 파일의 이름은 Page, ViewModel μ ‘λ―Έμ–΄λ₯Ό μ œμ™Έν•œ μ΄λ¦„λ§Œ μž…λ ₯ν•©λ‹ˆλ‹€.
  • νŒŒμΌμ΄λ¦„μ€ 클래슀 μ΄λ¦„μœΌλ‘œ μ‚¬μš©κ°€λŠ₯ν•œ 영문자 λ˜λŠ” _ 둜 μ‹œμž‘ν•˜κ³  문자, 숫자, _ 만으둜 μž…λ ₯ν•©λ‹ˆλ‹€.

ꢌμž₯사항:

  • μ•„μ΄ν…œ ν…œν”Œλ¦ΏμœΌλ‘œ ν•­λͺ©μ„ μΆ”κ°€ν•œ ν›„ Page νŒŒμΌμ€ Pages λ””λ ‰ν„°λ¦¬λ‘œ, ViewModel νŒŒμΌμ€ ViewModels λ””λ ‰ν„°λ¦¬λ‘œ 이동해야 ν•©λ‹ˆλ‹€.

MyTemplate.vstemplate 파일의 λ‚΄μš©

<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Item">
    <TemplateData>
    <DefaultName>Only name of page without postfix.xaml</DefaultName>
    <Name>Kr.Bbon.Product Xamarin Page with ViewModel</Name>
    <Description>Page and ViewModels Template with SyncFusion: Create on PROJECT ROOT then move Pages and ViewModels directory.</Description>
    <ProjectType>CSharp</ProjectType>
    <SortOrder>10</SortOrder>
    <Icon>__TemplateIcon.png</Icon>
    <PreviewImage>__PreviewImage.png</PreviewImage>
    </TemplateData>
    <TemplateContent>
    <References />
    <ProjectItem SubType="Designer" TargetFileName="$fileinputname$Page.xaml" ReplaceParameters="true">Page.xaml</ProjectItem>
    <ProjectItem SubType="Code" TargetFileName="$fileinputname$Page.xaml.cs" ReplaceParameters="true">Page.xaml.cs</ProjectItem>
    <ProjectItem SubType="Code" TargetFileName="$fileinputname$ViewModel.cs" ReplaceParameters="true">ViewModel.cs</ProjectItem>
    </TemplateContent>
</VSTemplate>

Page.xaml 파일의 λ‚΄μš©

<?xml version="1.0" encoding="utf-8" ?>
<core:AppContentPage xmlns="http://xamarin.com/schemas/2014/forms"
                        xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                        xmlns:d="http://xamarin.com/schemas/2014/forms/design"
                        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
                        xmlns:local="clr-namespace:$rootnamespace$"
                        xmlns:core="clr-namespace:Kr.Bbon.Core;assembly=Kr.Bbon.Core"
                        xmlns:behaviors="clr-namespace:Kr.Bbon.Core.Behaviors;assembly=Kr.Bbon.Core"
                        xmlns:converter="clr-namespace:Kr.Bbon.Core.Converters;assembly=Kr.Bbon.Core"
                        xmlns:viewmodel="clr-namespace:$rootnamespace$.ViewModels"
                        xmlns:fa="clr-namespace:Kr.Bbon.Styles.FontAwesome;assembly=Kr.Bbon.Styles.FontAwesome"
                        xmlns:buttons="clr-namespace:Syncfusion.XForms.Buttons;assembly=Syncfusion.Buttons.XForms"
                        xmlns:inputLayout="clr-namespace:Syncfusion.XForms.TextInputLayout;assembly=Syncfusion.Core.XForms"
                        mc:Ignorable="d"
                        x:Class="$rootnamespace$.Pages.$fileinputname$Page"
                        x:TypeArguments="viewmodel:$fileinputname$ViewModel"
                        Title="{Binding Title}"
                        Shell.NavBarIsVisible="False"
                        NavigationPage.HasNavigationBar="False">
    <ContentPage.Resources>
        <converter:FirstValidationErrorConverter x:Key="firstValidationErrorCoverter" />
        <converter:ValidationResultHasErrorConverter x:Key="validationResultHasErrorConverter" />
    </ContentPage.Resources>
    <ContentPage.Content>
        <AbsoluteLayout HorizontalOptions="FillAndExpand"
                        VerticalOptions="FillAndExpand"
                        Padding="0">
            <ScrollView Orientation="Vertical"
                        AbsoluteLayout.LayoutBounds="1.0, 1.0, 1.0, 1.0"
                        AbsoluteLayout.LayoutFlags="All"
                        HorizontalOptions="FillAndExpand"
                        Padding="0, 0, 0, 0">
                <StackLayout Orientation="Vertical">

                <!-- Content here!! -->
                <Label Text="Hello Xamarin" />

                </StackLayout>
            </ScrollView>
            <StackLayout IsVisible="{Binding IsBusy}"
                            AbsoluteLayout.LayoutBounds="1.0, 1.0, 1.0, 1.0"
                            AbsoluteLayout.LayoutFlags="All"
                            HorizontalOptions="FillAndExpand"
                            VerticalOptions="FillAndExpand"
                            Orientation="Vertical"
                            BackgroundColor="#50000000">
                <ActivityIndicator HorizontalOptions="Fill"
                                    VerticalOptions="CenterAndExpand"
                                    IsRunning="True" />
            </StackLayout>
        </AbsoluteLayout>
    </ContentPage.Content>
</core:AppContentPage>

Page.xaml.cs 파일의 λ‚΄μš©

using Kr.Bbon.Core;
using $rootnamespace$.ViewModels;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;

namespace $rootnamespace$.Pages
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    [Route(RouteUri.$fileinputname$)]
    public partial class $fileinputname$Page : AppContentPage<$fileinputname$ViewModel>
    {
        public $fileinputname$Page()
            : base()
        {
            InitializeComponent();
        }
    }
}

ViewModel.cs 파일의 λ‚΄μš©

using Kr.Bbon.Core;
using Kr.Bbon.Core.Validations;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Xamarin.Forms;

namespace $rootnamespace$.ViewModels
{
    public class $fileinputname$ViewModel : ViewModelBase
    {
        #region CONSTANTS

        #endregion

        #region Constructors
        
        public $fileinputname$ViewModel()
            : base()
        {
            Title = "Title Here";
        }

        #endregion

        #region Commands

        #endregion

        #region Properties
        
        #endregion
        
        protected override void InitializeCommands()
        {
            // Initialize Commands

            base.InitializeCommands();
        }

        protected override void AddValidations()
        {
            base.AddValidations();

            // Add properties validation rule  
        }

        #region Methods

        #endregion

        #region Properties private fields 

        #endregion
        
        #region local variables

        #endregion
    }
}

ν•΄λ‹Ή νŒŒμΌμ„ ν•˜λ‚˜μ˜ .zip 파일둜 내보내기 ν•©λ‹ˆλ‹€.

.zip νŒŒμΌμ€ μ•„λž˜μ™€ 같이 λͺ¨λ“  νŒŒμΌμ„ ν¬ν•¨ν•˜κ³  μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€.

MyXamarin.PageWithViewMode.zip
- __PreviewImage.png
- __TemplateIcon.png
- MyTemplate.vstemplate
- Page.xaml
- Page.xaml.cs
- ViewModel.cs

μ•„μ΄ν…œ ν…œν”Œλ¦Ώ .zip νŒŒμΌμ„ μ•„μ΄ν…œ ν…œν”Œλ¦Ώ 디렉터리에 λ³΅μ‚¬ν•©λ‹ˆλ‹€.

Visual Studio κ°€ 싀행쀑이면 μž¬μ‹œμž‘ν•΄μ•Ό μΆ”κ°€λœ μ•„μ΄ν…œ ν…œν”Œλ¦Ώμ„ 읽어 λ“€μž…λ‹ˆλ‹€.

μ†”λ£¨μ…˜ 탐색기 ν˜Ήμ€ 파일 λ©”λ‰΄μ—μ„œ μƒˆ ν•­λͺ© μΆ”κ°€ 메뉴λ₯Ό μ‹œμž‘ν•˜λ©΄ μΆ”κ°€ν•œ μ•„μ΄ν…œ ν…œν”Œλ¦Ώμ„ 선택할 수 μžˆμŠ΅λ‹ˆλ‹€.

vs item template add new item

μ œμ•½μ‘°κ±΄μ— 맞게 μ˜¬λ°”λ₯Έ 이름을 μž…λ ₯ν•˜κ³  μΆ”κ°€ν•˜λ©΄ ν”„λ‘œμ νŠΈ 루트 디렉터리에 파일이 μΆ”κ°€λ©λ‹ˆλ‹€.

이름을 Hello 라고 μž…λ ₯ν•˜λ©΄, μ•„λž˜μ™€ 같이 파일이 λ§Œλ“€μ–΄ μ§‘λ‹ˆλ‹€.

- HelloPage.xaml
- HelloPage.xaml.cs
- HelloViewModel.cs

μ €λŠ” 이제 Page λŠ” Pages 디렉터리에 ViewModel 은 ViewModels λ””λ ‰ν„°λ¦¬μ—μ„œ κ΄€λ¦¬ν•˜λ―€λ‘œ 각 λ””λ ‰ν„°λ¦¬λ‘œ 이동 ν›„ κ΅¬ν˜„μ„ μ‹œμž‘ν•˜λ©΄ λ©λ‹ˆλ‹€.