자습서의 이 부분에서는 데이터 뷰 및 모델의 개념을 소개합니다.
자습서의 이전 단계에서는 사용자가 단일 노트를 저장, 편집 또는 삭제할 수 있는 새 페이지를 프로젝트에 추가했습니다. 그러나 앱이 둘 이상의 메모를 처리해야 하므로 모든 노트를 표시하는 다른 페이지를 추가해야 합니다 AllNotesPage(호출). 이 페이지에서 사용자가 편집기 페이지에서 열 메모를 선택하여 보거나 편집하거나 삭제할 수 있습니다. 또한 사용자가 새 메모를 만들 수 있도록 해야 합니다.
이렇게 AllNotesPage 하려면 노트 컬렉션과 컬렉션을 표시하는 방법이 있어야 합니다. 메모 데이터가 파일에 밀접하게 바인딩되어 있기 때문에 앱이 문제가 발생합니다 NotePage . 여기에서 AllNotesPage는 만든 날짜 및 텍스트 미리 보기와 같은 각 노트에 대한 정보를 사용하여 목록 또는 다른 컬렉션 보기의 모든 노트를 표시하려고 합니다. 노트 텍스트가 컨트롤에 TextBox 단단히 바인딩되어 있으므로 이 작업을 수행할 방법이 없습니다.
모든 노트를 표시하는 페이지를 추가하기 전에 노트 데이터를 메모 프레젠테이션과 구분하기 위해 몇 가지 변경 사항을 적용해 보겠습니다.
보기 및 모델
일반적으로 WinUI 앱에는 뷰 계층 과 데이터 계층 이상이 있습니다.
뷰 계층은 XAML 태그를 사용하여 UI를 정의합니다. 태그에는 특정 UI 구성 요소와 데이터 멤버 간의 연결을 정의하는 데이터 바인딩 식(예: x:Bind)이 포함됩니다. 코드 숨김 파일은 경우에 따라 뷰 계층의 일부로 사용되어 UI를 사용자 지정하거나 조작하거나 데이터에서 작업을 수행하는 메서드를 호출하기 전에 이벤트 처리기 인수에서 데이터를 추출하는 데 필요한 추가 코드를 포함합니다.
데이터 계층 또는 모델은 앱 데이터 및 관련 논리를 나타내는 형식을 정의합니다. 이 계층은 뷰 계층과 독립적이며 데이터와 상호 작용하는 여러 보기를 만들 수 있습니다.
현재는 NotePage 데이터 보기(메모 텍스트)를 나타냅니다. 그러나 시스템 파일에서 앱으로 데이터를 읽은 후에는 in의 TextTextBox속성에 NotePage 만 존재합니다. 다른 방식으로 또는 다른 위치에 데이터를 표시할 수 있는 방식으로 앱에 표시되지 않습니다. 즉, 앱에 데이터 계층이 없습니다. 이제 프로젝트를 재구성하여 데이터 계층을 만듭니다.
보기 및 모델 구분
팁 (조언)
GitHub 리포지토리에서 이 자습서의 코드를 다운로드하거나 볼 수 있습니다. 이 단계에서 코드를 보려면 다음 커밋을 참조하세요. 참고 페이지 - 뷰 모델.
기존 코드를 리팩터링하여 모델을 뷰와 분리합니다. 다음 몇 단계에서는 뷰와 모델이 서로 별도로 정의되도록 코드를 구성합니다.
솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 WinUINotes 클릭하고새 폴더>를 선택합니다. 폴더 이름을 Models로 지정합니다.
프로젝트를 다시 마우스 오른쪽 단추로 WinUINotes 클릭하고새 폴더>를 선택합니다. 폴더 이름을 Views로 지정합니다.
NotePage.xaml 항목을 찾아 폴더로 끌어옵니다Views. NotePage.xaml.cs 파일이 함께 이동해야 합니다.
비고
파일을 이동할 때 Visual Studio는 일반적으로 이동 작업에 시간이 오래 걸릴 수 있는 방법에 대한 경고를 표시합니다. 여기서는 문제가 되지 않습니다. 이 경고가 표시되면 [확인]을 누릅니다.
Visual Studio에서 이동된 파일의 네임스페이스를 조정할지 묻는 메시지가 표시될 수도 있습니다. 아니요를 선택합니다. 다음 단계에서 네임스페이스를 변경합니다.
보기 네임스페이스 업데이트
보기가 폴더로 Views 이동되었으므로 일치하도록 네임스페이스를 업데이트해야 합니다. 페이지의 XAML 및 코드 숨김 파일에 대한 네임스페이스가 로 설정 WinUINotes됩니다. 이 작업은 .로 업데이트해야 합니다 WinUINotes.Views.
솔루션 탐색기 창에서 확장 NotePage.xaml 하여 코드 숨김 파일을 표시합니다.
아직 열려 있지 않은 경우 항목을 두 번 클릭하여 NotePage.xaml.cs 코드 편집기를 엽니다. 네임스페이스를 다음으로
WinUINotes.Views변경합니다.namespace WinUINotes.Views아직 열려 있지 않은 경우 항목을 두 번 클릭하여 NotePage.xaml XAML 편집기를 엽니다. 이전 네임스페이스는 XAML의
x:Class코드 숨김 클래스 형식을 정의하는 특성을 통해 참조됩니다. 이 항목은 네임스페이스가 아니라 형식이 있는 네임스페이스입니다.x:Class값을WinUINotes.Views.NotePage로 변경합니다.x:Class="WinUINotes.Views.NotePage"
MainWindow에서 네임스페이스 참조 수정
이전 단계에서는 메모 페이지를 만들고 해당 페이지로 이동하도록 업데이트 MainWindow.xaml 했습니다. 네임스페이스 매핑과 local: 매핑되었습니다. 이름을 local 프로젝트의 루트 네임스페이스에 매핑하는 것이 일반적이며 Visual Studio 프로젝트 템플릿은 이미 이 작업을 수행합니다(xmlns:local="using:WinUINotes"). 이제 페이지가 새 네임스페이스로 이동했으므로 XAML의 형식 매핑이 잘못되었습니다.
다행히 필요에 따라 고유한 네임스페이스 매핑을 추가할 수 있습니다. 프로젝트에서 만든 다른 폴더의 항목에 액세스하려면 이 작업을 수행해야 합니다. 이 새 XAML 네임스페이스는 네임스페이스에 WinUINotes.Views매핑되므로 이름을 지정합니다 views. 선언은 다음 특성 xmlns:views="using:WinUINotes.Views"과 같이 표시됩니다.
솔루션 탐색기 창에서 MainWindow.xaml 항목을 두 번 클릭하여 XAML 편집기에서 엽니다.
다음의 매핑 아래 줄에 이 새 네임스페이스 매핑을 추가합니다
local.xmlns:views="using:WinUINotes.Views"localXAML 네임스페이스는 속성을 설정하는Frame.SourcePageType데 사용되었으므로 해당 속성으로views변경합니다. 이제 XAML은 다음과 같이 표시됩니다.<Window x:Class="WinUINotes.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:WinUINotes" xmlns:views="using:WinUINotes.Views" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Title="WinUI Notes"> <!-- ... Unchanged XAML not shown. --> <Frame x:Name="rootFrame" Grid.Row="1" SourcePageType="views:NotePage"/> <!-- ... Unchanged XAML not shown. --> </Window>앱을 빌드하고 실행합니다. 앱은 컴파일러 오류 없이 실행되어야 하며 모든 항목이 이전과 같이 작동해야 합니다.
모델 정의
현재 모델(데이터)은 메모 보기에 포함되어 있습니다. 노트 페이지의 데이터를 나타내는 새 클래스를 만듭니다.
솔루션 탐색기 창에서 폴더를 Models 마우스 오른쪽 단추로 클릭하고 클래스 추가>를 선택합니다.
클래스 Note.cs 이름을 지정하고 Add 키를 누릅니다. Note.cs 파일이 코드 편집기에서 열립니다.
파일의 Note.cs 코드를 이 코드로 바꿔 클래스
public를 만들고 메모를 처리하기 위한 속성과 메서드를 추가합니다.using System; using System.Threading.Tasks; using Windows.Storage; namespace WinUINotes.Models { public class Note { private StorageFolder storageFolder = ApplicationData.Current.LocalFolder; public string Filename { get; set; } = string.Empty; public string Text { get; set; } = string.Empty; public DateTime Date { get; set; } = DateTime.Now; public Note() { Filename = "notes" + DateTime.Now.ToBinary().ToString() + ".txt"; } public async Task SaveAsync() { // Save the note to a file. StorageFile noteFile = (StorageFile)await storageFolder.TryGetItemAsync(Filename); if (noteFile is null) { noteFile = await storageFolder.CreateFileAsync(Filename, CreationCollisionOption.ReplaceExisting); } await FileIO.WriteTextAsync(noteFile, Text); } public async Task DeleteAsync() { // Delete the note from the file system. StorageFile noteFile = (StorageFile)await storageFolder.TryGetItemAsync(Filename); if (noteFile is not null) { await noteFile.DeleteAsync(); } } } }파일을 저장합니다.
이 코드는 코드와 매우 유사 NotePage.xaml.cs하며 몇 가지 변경 및 추가가 있습니다.
Filename 속성 Text 으로 public 변경되었으며 새 Date 속성이 추가되었습니다.
파일을 저장하고 삭제하는 코드가 메서드에 public 배치되었습니다. 단추 이벤트 처리기에서 ClickNotePage사용한 코드와 대부분 동일하지만 파일이 삭제된 후 보기를 업데이트하는 추가 코드가 제거되었습니다. 데이터 바인딩을 사용하여 모델과 뷰를 동기화된 상태로 유지하므로 여기서는 필요하지 않습니다.
이러한 비동기 메서드 서명은 .void 이 클래스는 Task 값을 반환하지 않는 단일 비동기 작업을 나타냅니다. 메서드 서명에 필요한 void경우가 아니면 이벤트 처리기의 Click 경우 async 와 마찬가지로 메서드는 .를 Task반환해야 합니다.
또한 더 이상 메모를 보관하는 참조를 StorageFile 유지하지 않습니다. 파일을 저장하거나 삭제해야 할 때 가져오기만 하면 됩니다.
에서 NotePage파일 이름 note.txt에 자리 표시자를 사용했습니다. 이제 앱에서 둘 이상의 노트를 지원하므로 저장된 노트의 파일 이름은 서로 다르고 고유해야 합니다. 이렇게 하려면 생성자에서 속성을 설정합니다 Filename .
DateTime.ToBinary 메서드를 사용하여 현재 시간에 따라 파일 이름의 일부를 만들고 파일 이름을 고유하게 만들 수 있습니다. 생성된 파일 이름은 다음과 notes-8584626598945870392.txt같습니다.
메모 페이지 업데이트
이제 데이터 모델을 사용하도록 NotePage 보기를 업데이트 Note 하고 모델로 이동된 코드를 삭제할 Note 수 있습니다.
편집기에서 아직 열려 있지 않은 경우 Views\NotePage.xaml.cs 파일을 엽니다.
페이지 맨 위에 있는 마지막
using문 후에 새using문을 추가하여 폴더 및 네임스페이스의 클래스에Models대한 코드 액세스 권한을 부여합니다.using WinUINotes.Models;클래스에서 다음 줄을 삭제합니다.
private StorageFolder storageFolder = ApplicationData.Current.LocalFolder; private StorageFile? noteFile = null; private string fileName = "note.txt";대신 해당 위치에 명명된
NotenoteModel개체를 추가합니다. 뷰를 제공하는 메모 데이터를NotePage나타냅니다.private Note? noteModel;또한 이벤트 처리기가
NotePage_Loaded더 이상 필요하지 않습니다. 텍스트 파일에서 TextBox로 직접 텍스트를 읽지 않습니다. 대신 노트 텍스트를 개체로 읽습니다Note. 이후 단계에서 추가할 때 이에 대한 코드를 추가AllNotesPage합니다. 이러한 줄을 삭제합니다.Loaded += NotePage_Loaded; ... private async void NotePage_Loaded(object sender, RoutedEventArgs e) { noteFile = (StorageFile)await storageFolder.TryGetItemAsync(fileName); if (noteFile is not null) { NoteEditor.Text = await FileIO.ReadTextAsync(noteFile); } }메서드의 코드를
SaveButton_Click다음으로 바꿉다.if (noteModel is not null) { await noteModel.SaveAsync(); }메서드의 코드를
DeleteButton_Click다음으로 바꿉다.if (noteModel is not null) { await noteModel.DeleteAsync(); }
이제 모델을 사용하도록 Note XAML 파일을 업데이트할 수 있습니다. 이전에는 텍스트 파일에서 코드 숨김 파일의 TextBox.Text 속성으로 직접 텍스트를 읽었습니다. 이제 속성에 대한 데이터 바인딩을 Text 사용합니다.
편집기에서 아직 열려 있지 않은 경우 Views\NotePage.xaml 파일을 엽니다.
컨트롤에
Text특성을 추가합니다TextBox. 다음Text의noteModel속성에Text="{x:Bind noteModel.Text, Mode=TwoWay}"바인딩합니다.다음의
HeaderDatenoteModel속성에Header="{x:Bind noteModel.Date.ToString()}"바인딩하도록 업데이트합니다.<TextBox x:Name="NoteEditor" <!-- ↓ Add this line. ↓ --> Text="{x:Bind noteModel.Text, Mode=TwoWay}" AcceptsReturn="True" TextWrapping="Wrap" PlaceholderText="Enter your note" <!-- ↓ Update this line. ↓ --> Header="{x:Bind noteModel.Date.ToString()}" ScrollViewer.VerticalScrollBarVisibility="Auto" Width="400" Grid.Column="1"/>
데이터 바인딩은 앱의 UI에서 데이터를 표시하고 필요에 따라 해당 데이터와 동기화 상태를 유지하는 방법입니다. 바인딩의 설정은 Mode=TwoWay 및 TextBox.Text 속성이 noteModel.Text 자동으로 동기화됨을 의미합니다. 텍스트가 업데이트TextBox되면 변경 내용이 해당 속성Text에 noteModel 반영되고 변경된 경우 noteModel.Text 업데이트가 반영됩니다TextBox.
이 속성은 Header 파일을 만든 후 속성이 Mode 변경되지 않으므로 기본값 OneTimenoteModel.Date 을 사용합니다. 또한 이 코드는 바인딩 경로의 x:Bind 단계와 같은 함수를 사용할 수 있는 함수 ToString이라는 강력한 기능을 보여 줍니다.
중요합니다
올바른 BindingMode를 선택하는 것이 중요합니다. 그렇지 않으면 데이터 바인딩이 예상대로 작동하지 않을 수 있습니다. (일반적인 실수 {x:Bind} 는 필요할 때 BindingModeOneWay 기본값 TwoWay 을 변경하는 것을 잊어버리는 것입니다.)
| 이름 | Description |
|---|---|
OneTime |
바인딩이 만들어지는 경우에만 대상 속성을 업데이트합니다. 에 대한 기본값입니다 {x:Bind}. |
OneWay |
바인딩을 만들 때 대상 속성을 업데이트합니다. 원본 개체에 대한 변경 내용이 대상에 전파할 수도 있습니다. 에 대한 기본값입니다 {Binding}. |
TwoWay |
둘 중 하나가 변경되면 대상 또는 원본 개체를 업데이트합니다. 바인딩이 만들어지면 대상 속성이 원본에서 업데이트됩니다. |
데이터 바인딩은 데이터와 UI의 분리를 지원하며, 이로 인해 앱의 가독성, 테스트 가능성 및 유지 관리 효율성이 향상되고 더 간단한 개념적 모델이 됩니다.
WinUI에는 다음 두 가지 종류의 바인딩 중에서 선택할 수 있습니다.
-
{x:Bind}태그 확장은 컴파일 시간에 처리됩니다. 그 이점 중 일부는 바인딩 식의 성능 향상 및 컴파일 시간 유효성 검사입니다. WinUI 앱에서 바인딩하는 것이 좋습니다. - 태그 확장은
{Binding}런타임에 처리되며 범용 런타임 개체 검사를 사용합니다.
다음 문서에서 자세히 알아보세요.
데이터 바인딩 및 MVVM
MVVM(Model-View-ViewModel)은 .NET 개발자에게 인기 있는 UI 및 비 UI 코드를 분리하기 위한 UI 아키텍처 디자인 패턴입니다. WinUI 앱을 만드는 방법에 대해 자세히 알아보면 언급된 내용을 보고 들을 수 있습니다. 여기에서 수행한 것처럼 보기와 모델을 분리하는 것은 앱의 전체 MVVM 구현을 향한 첫 번째 단계이지만 이 자습서에서는 이 단계를 진행합니다.
비고
이 자습서에서는 데이터 모델을 참조하기 위해 "model"이라는 용어를 사용했지만, 이 모델은 전체 MVVM 구현에서 ViewModel 과 더 밀접하게 정렬되는 동시에 모델의 측면을 통합한다는 점에 유의해야 합니다.
MVVM에 대한 자세한 내용은 다음 리소스를 참조하세요.
Windows developer