es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

WPF) Notificar al ViewModel que una propiedad ha cambiado en el código detrás.

Tengo un control de usuario que contiene un cuadro de texto. Estoy utilizando los eventos integrados “TextChanged” y “LostFocus” en el código detrás. Aquí verifico si la entrada es válida y actualizo una enumeración llamada “Status” dependiendo del valor ingresado en el cuadro de texto.

Mi problema es que tengo código en la parte “set” de la propiedad “Status” en el Modelo de Vista, pero ese código no se ejecuta cuando establezco “Status” en algo en el código detrás.

Entonces, lo que me gustaría hacer es actualizar el enlace desde el código detrás, para que cuando ingrese un texto no válido en el cuadro de texto, se notifique al Modelo de Vista.

¿O es esto una mala práctica según MVVM? ¿Debería en su lugar enlazar los eventos “LostFocus” y “TextChanged” al Modelo de Vista y hacer el código allí en su lugar?

(Estoy utilizando el “ObservableObject” integrado en el kit MVVM de Microsoft).

(Mi pregunta es bastante general y no muy específica para mi código, pero aquí hay parte de mi código en caso de que sea necesario para responder mi pregunta)

Código detrás

public SyncStatus Status
{
    get { return (SyncStatus)GetValue(StatusProperty); }
    set { SetValue(StatusProperty, value); }
}

public static readonly DependencyProperty StatusProperty = DependencyProperty.Register("Status", typeof(SyncStatus), typeof(ParamNodeV), new PropertyMetadata(SyncStatus.OK));

private void TextBox_TextChanged(object sender, RoutedEventArgs e)
{
    //código irrelevante eliminado
    Status = SyncStatus.ERROR;
    else
    Status = SyncStatus.NOTSYNCED;
    //código irrelevante eliminado
}

Modelo de Vista:

SyncStatus status;
public SyncStatus Status
{
    get
    {
        SyncStatus childrensStatus = GetChildrensStatus();
        if (childrensStatus != SyncStatus.OK)
            return childrensStatus;
        return status;
    }
    set // ESTO NO SE LLAMA CUANDO SE ESTABLECE STATUS EN EL CÓDIGO DETRÁS
    {
        status = value;
        if (SyncParent != null)
            SyncParent.Sync(this);
        else
            Trace.WriteLine("syncparent is null");
        OnPropertyChanged(nameof(Status));
    }
}

(y sí, establecer el estado en el Modelo de Vista actualiza la vista, por lo que el enlace funciona, simplemente no desde el código detrás)

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Generalmente se considera una mala práctica actualizar directamente el modelo de vista desde el código detrás en MVVM. En su lugar, deberías enlazar los eventos relevantes (en este caso, TextChanged y LostFocus) a comandos en el modelo de vista, y manejar la validación y actualizaciones allí.

    Puedes crear comandos en el modelo de vista implementando la interfaz ICommand o utilizando una biblioteca de enlaces de comandos como Prism o MVVM Light. Cuando se desencadenen los eventos, los comandos se ejecutarán y podrás realizar la lógica correspondiente en el modelo de vista.

    Si realmente necesitas actualizar el modelo de vista desde el código detrás, puedes utilizar el método OnPropertyChanged de ObservableObject para generar el evento PropertyChanged en la propiedad relevante. Sin embargo, esto debe usarse con moderación y solo cuando no haya alternativa.

Comments are closed.