Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En esta parte del tutorial se presentan los conceptos de vistas y modelos de datos.
En los pasos anteriores del tutorial, agregó una nueva página a la project que permite al usuario guardar, editar o eliminar una sola nota. Sin embargo, dado que la aplicación necesita controlar más de una nota, debe agregar otra página que muestre todas las notas (llámala AllNotesPage). Esta página permite al usuario elegir una nota para abrirla en la página del editor para que pueda verlo, editarlo o eliminarlo. También debe permitir que el usuario cree una nueva nota.
Para ello, AllNotesPage debe tener una colección de notas y una manera de mostrar la colección. Aquí es donde la aplicación tiene problemas porque los datos de la nota están estrechamente enlazados al NotePage archivo. En AllNotesPage, solo desea mostrar todas las notas de una lista u otra vista de colección, con información sobre cada nota, como la fecha en que se creó y una vista previa del texto. Con el texto de la nota que está estrechamente enlazado al control TextBox, no hay forma de hacer esto.
Antes de agregar una página para mostrar todas las notas, vamos a realizar algunos cambios para separar los datos de notas de la presentación de la nota.
Vistas y modelos
Normalmente, una aplicación WinUI 3 tiene al menos una capa de vista y una capa de datos.
La capa de vista define la interfaz de usuario mediante el marcado XAML. El marcado incluye expresiones de enlace de datos (como x:Bind) que definen la conexión entre componentes específicos de la interfaz de usuario y miembros de datos. A veces, los archivos de código subyacente se usan como parte de la capa de vista para contener código adicional necesario para personalizar o manipular la interfaz de usuario, o para extraer datos de argumentos del controlador de eventos antes de llamar a un método que realiza el trabajo en los datos.
La capa de datos o el modelo definen los tipos que representan los datos de la aplicación y la lógica relacionada. Esta capa es independiente de la capa de vista y puede crear varias vistas diferentes que interactúen con los datos.
Actualmente, NotePage representa una vista de datos (el texto de la nota). Sin embargo, después de leer los datos en la aplicación desde el archivo del sistema, solo existe en la Text propiedad de TextBox en NotePage. No se representa en la aplicación de una manera que le permite presentar los datos de maneras diferentes o en diferentes lugares; es decir, la aplicación no tiene una capa de datos. Reestructura el proyecto ahora para crear la capa de datos.
Separar la vista y el modelo
Sugerencia
Puede descargar o ver el código de este tutorial desde el repositorio GitHub. Para ver el código tal como está en este paso, consulte esta confirmación: note page - view-model.
Refactoriza el código existente para separar el modelo de la vista. Los pasos siguientes organizarán el código para que las vistas y los modelos se definan por separado entre sí.
En Solution Explorer, haga clic con el botón derecho en el WinUINotes project y seleccione Agregar>Nueva carpeta. Asigna a la carpeta el nombre Models.
Haga clic con el botón derecho en el WinUINotes project y seleccione Agregar>Nueva carpeta. Asigna a la carpeta el nombre Views.
Busque el NotePage.xaml elemento y arrástrelo a la Views carpeta . El NotePage.xaml.cs archivo debe moverse junto con este.
Nota:
Al mover un archivo, Visual Studio normalmente le pide una advertencia sobre cómo la operación de traslado puede tardar mucho tiempo. Esto no debería ser un problema aquí, presiona Aceptar si ves esta advertencia.
Visual Studio también puede preguntar si desea ajustar el espacio de nombres del archivo movido. Seleccione No. Cambiará el espacio de nombres en los pasos siguientes.
Actualización del espacio de nombres
Ahora que la vista se ha movido a la Views carpeta, deberá actualizar los espacios de nombres para que coincidan. El espacio de nombres para XAML y los archivos de código subyacente de las páginas se establece en WinUINotes. Debe actualizarse a WinUINotes.Views.
En el panel Solution Explorer, expanda NotePage.xaml para mostrar el archivo de código subyacente.
Haga doble clic en el NotePage.xaml.cs elemento para abrir el editor de código si aún no está abierto. Cambia el espacio de nombres a
WinUINotes.Views.namespace WinUINotes.ViewsHaga doble clic en el NotePage.xaml elemento para abrir el editor XAML si aún no está abierto. La referencia al espacio de nombres antiguo se hace a través del atributo
x:Class, que define qué tipo de clase es el código subyacente para XAML. Esta entrada no es solo el espacio de nombres, sino el espacio de nombres con el tipo. Cambie el valor dex:ClassaWinUINotes.Views.NotePage:x:Class="WinUINotes.Views.NotePage"
Corrige la referencia de espacio de nombres en MainWindow
En el paso anterior, creó la página de notas y actualizó MainWindow.xaml para navegar a ella. Recuerde que se asignó con el mapeo del espacio de nombres local:. Es habitual asignar el nombre local al espacio de nombres raíz de su proyecto, y la plantilla de proyecto de Visual Studio ya lo hace por usted (xmlns:local="using:WinUINotes"). Ahora que la página se ha movido a un nuevo espacio de nombres, la asignación de tipos en XAML ahora no es válida.
Afortunadamente, puede agregar sus propias asignaciones de espacio de nombres según sea necesario. Para acceder a los elementos en diferentes carpetas que cree en su proyecto, necesita hacer esto. Este nuevo espacio de nombres XAML se asignará al espacio de nombres de WinUINotes.Views, por lo que asígnele el nombre views. La declaración debe tener un aspecto similar al siguiente atributo: xmlns:views="using:WinUINotes.Views".
En el panel Solution Explorer, haga doble clic en la entrada MainWindow.xaml para abrirla en el editor XAML.
Agregue este nuevo mapeo de espacio de nombres en la línea debajo del mapeo para
local:xmlns:views="using:WinUINotes.Views"El
localespacio de nombres XAML se usó para establecer laFrame.SourcePageTypepropiedad, así que cámbiela aviewsallí. El XAML debería tener ahora un aspecto similar al siguiente:<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>Compile y ejecute la aplicación. La aplicación debe ejecutarse sin errores del compilador y todo debería seguir funcionando como antes.
Definición del modelo
Actualmente, el modelo (los datos) está incrustado en la vista de notas. Creará una nueva clase para representar los datos de una página de notas:
En el panel Solution Explorer, haga clic con el botón derecho en la carpeta Models y seleccione Add>Class... .
Asigne un nombre a la clase Note.cs y presione Agregar. El Note.cs archivo se abrirá en el editor de código.
Reemplace el código del Note.cs archivo por este código, que hace que la clase
publicy agregue propiedades y métodos para controlar una nota: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(); } } } }Guarde el archivo.
Observará que este código es muy similar al código de NotePage.xaml.cs, con algunos cambios y adiciones.
Filename y Text se han cambiado a public propiedades y se ha agregado una nueva Date propiedad.
El código para guardar y eliminar los archivos se ha colocado en public métodos. Es principalmente idéntico al código que usó en los controladores de eventos del botón Click en NotePage, pero se ha eliminado el código adicional para actualizar la vista después de que el archivo sea eliminado. No es necesario aquí porque va a usar el enlace de datos para mantener sincronizado el modelo y la vista.
Estas firmas de método asincrónico devuelven Task en lugar de void. La Task clase representa una única operación asincrónica que no devuelve un valor. A menos que la firma del método requiera void, como es el caso de los Click controladores de eventos, async los métodos deben devolver un Task.
Tampoco mantendrá una referencia a la StorageFile que contiene la nota. Solo intenta obtener el archivo cuando lo necesite para guardar o eliminar.
En NotePage, utilizaste un marcador de posición para el nombre del archivo: note.txt. Ahora que la aplicación admite más de una nota, los nombres de archivo de las notas guardadas deben ser diferentes y únicos. Para hacer esto, establezca la propiedad Filename en el constructor. Puede usar el método DateTime.ToBinary para crear una parte del nombre de archivo en función de la hora actual y hacer que los nombres de archivo sean únicos. El nombre de archivo generado tiene este aspecto: notes-8584626598945870392.txt.
Actualizar la página de notas
Ahora puede actualizar la NotePage vista para usar el Note modelo de datos y eliminar código que se ha movido al Note modelo.
Abra el archivo Views\NotePage.xaml.cs si aún no está abierto en el editor.
Después de la última instrucción
usingen la parte superior de la página, agregue una nueva instrucciónusingpara proporcionar al código acceso a las clases de la carpetaModelsy el espacio de nombres.using WinUINotes.Models;Elimine estas líneas de la clase :
private StorageFolder storageFolder = ApplicationData.Current.LocalFolder; private StorageFile? noteFile = null; private string fileName = "note.txt";En su lugar, agregue un
Noteobjeto denominadonoteModel. Esto representa los datos de nota de los cualesNotePageproporciona una vista.private Note? noteModel;Ya no necesita el
NotePage_Loadedcontrolador de eventos. No leerá texto directamente desde el archivo de texto en el TextBox. En su lugar, el texto de la nota se leerá enNoteobjetos. Agregarás el código para esto cuando agregues elAllNotesPageen un paso posterior. Elimine estas líneas.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); } }Reemplace el código del
SaveButton_Clickmétodo por este:if (noteModel is not null) { await noteModel.SaveAsync(); }Reemplace el código del
DeleteButton_Clickmétodo por este:if (noteModel is not null) { await noteModel.DeleteAsync(); }
Ahora puedes actualizar el archivo XAML para usar el Note modelo. Anteriormente, se leía el texto directamente del archivo de texto en la TextBox.Text propiedad del archivo de código subyacente. Ahora, usas el enlace de datos para la propiedad Text.
Abra el archivo Views\NotePage.xaml si aún no está abierto en el editor.
Agregue un
Textatributo alTextBoxcontrol . Enlazarlo a laTextpropiedad denoteModel:Text="{x:Bind noteModel.Text, Mode=TwoWay}".Actualice el
Headerpara enlazar con la propiedadDatedenoteModel: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"/>
El enlace de datos es una manera de que la interfaz de usuario de la aplicación muestre datos y, opcionalmente, permanezca sincronizada con esos datos. La Mode=TwoWay configuración del enlace significa que las TextBox.Text propiedades y noteModel.Text se sincronizan automáticamente. Cuando el texto se actualiza en TextBox, los cambios se reflejan en la Text propiedad de noteModely, si noteModel.Text se cambia, las actualizaciones se reflejan en TextBox.
La Header propiedad usa el valor predeterminado Mode de OneTime porque la noteModel.Date propiedad no cambia después de crear el archivo. Este código también demuestra una poderosa característica de x:Bind llamada vinculación de funciones, que permite usar una función como ToString un paso en la ruta de enlace.
Importante
Es importante elegir el BindingMode correcto; De lo contrario, es posible que el enlace de datos no funcione según lo previsto. (Un error común con {x:Bind} es olvidar cambiar el valor predeterminado BindingMode cuando OneWay se necesita o TwoWay ).
| Nombre | Description |
|---|---|
OneTime |
Actualiza la propiedad de destino solo cuando se crea el enlace. Valor predeterminado para {x:Bind}. |
OneWay |
Actualiza la propiedad de destino cuando se crea el enlace. Los cambios en el objeto de origen también se pueden propagar al destino. Valor predeterminado para {Binding}. |
TwoWay |
Actualiza el destino o el objeto de origen cuando cambia. Cuando se crea el enlace, la propiedad de destino se actualiza desde el origen. |
El enlace de datos admite la separación de los datos y la interfaz de usuario, lo que da como resultado un modelo conceptual más sencillo, así como una mejor legibilidad, capacidad de prueba y mantenimiento de la aplicación.
En WinUI, hay dos tipos de enlaces entre los que puede elegir:
- La
{x:Bind}extensión de marcado se procesa en tiempo de compilación. Algunas de sus ventajas son un rendimiento mejorado y la validación en tiempo de compilación de las expresiones de enlace. Se recomienda para la vinculación en aplicaciones de WinUI. - La extensión de marcado
{Binding}se procesa en tiempo de ejecución y utiliza interrogación de objetos en tiempo de ejecución de uso general.
Obtenga más información en los documentos:
Enlace de datos y MVVM
Model-View-ViewModel (MVVM) es un patrón de diseño arquitectónico de la interfaz de usuario para desacoplar la interfaz de usuario y el código que no es de interfaz de usuario que es popular con los desarrolladores de .NET. Probablemente verá y escuchará lo mencionado a medida que obtenga más información sobre la creación de aplicaciones WinUI. Separar las vistas y los modelos, como lo has hecho aquí, es el primer paso hacia una implementación completa de MVVM para la aplicación, pero es hasta donde llegarás en este tutorial.
Nota:
Hemos usado el término "modelo" para hacer referencia al modelo de datos en este tutorial, pero es importante tener en cuenta que este modelo está más alineado con viewModel en una implementación completa de MVVM, al tiempo que incorpora aspectos del modelo.
Para más información sobre MVVM, consulte estos recursos: