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 al proyecto 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 TextBox control, no hay forma de hacerlo.
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 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. Ahora reestructurará el proyecto 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 de GitHub. Para ver el código tal como está en este paso, consulte esta confirmación: página de notas: modelo de vista.
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 el Explorador de soluciones, haga clic con el botón derecho en el WinUINotes proyecto y seleccione Agregar>nueva carpeta. Asigna a la carpeta el nombre Models.
Haga clic con el botón derecho en el WinUINotes proyecto de nuevo 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 con él.
Nota:
Al mover un archivo, Visual Studio normalmente te muestra una advertencia de que 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 deseas ajustar el espacio de nombres del archivo trasladado. 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 Explorador de soluciones, 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"
Corrección de 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 la asignación del local: espacio de nombres. Es habitual asignar el nombre al espacio local de nombres raíz del proyecto y la plantilla de proyecto de Visual Studio ya lo hace (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. Debe hacerlo para acceder a los elementos de diferentes carpetas que cree en el proyecto. Este nuevo espacio de nombres XAML se asignará al espacio de nombres de WinUINotes.Views, por lo que asígnelo viewsel nombre . La declaración debe tener un aspecto similar al siguiente atributo: xmlns:views="using:WinUINotes.Views".
En el panel Explorador de soluciones, haga doble clic en la entrada MainWindow.xaml para abrirla en el editor XAML.
Agregue esta nueva asignación de espacio de nombres en la línea debajo de la asignación 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 Explorador de soluciones, haz clic con el botón derecho en la carpeta Models y selecciona Agregar>Clase....
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 de botón Click en NotePage, pero código adicional para actualizar la vista después de eliminar el archivo. 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, usó un marcador de posición para el nombre de 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 ello, establezca la Filename propiedad 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
usinginstrucción de la parte superior de la página, agregue una nuevausinginstrucción para conceder acceso al código a las clases de la carpeta y elModelsespacio 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 denominadonoteModelen su lugar. Esto representa los datos de nota queNotePageproporcionan una vista de .private Note? noteModel;Ya no necesita el
NotePage_Loadedcontrolador de eventos. No leerá texto directamente desde el archivo de texto en textBox. En su lugar, el texto de la nota se leerá enNoteobjetos. Agregará el código para esto cuando agregue elAllNotesPageelemento en 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, usará el enlace de datos para la Text propiedad .
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 para
Headerenlazar a laDatepropiedad denoteModel: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 muestra una característica eficaz de llamado enlace de x:Bindfunciones, que permite usar una función como ToString un paso en la ruta de acceso 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 el enlace en aplicaciones WinUI. - La
{Binding}extensión de marcado se procesa en tiempo de ejecución y usa la inspecció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 ha hecho aquí, es el primer paso hacia una implementación completa de MVVM de la aplicación, pero es hasta donde vaya 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: