web-dev-qa-db-fra.com

La liaison WPF ne met pas à jour la vue

J'ai un bloc de texte:

<TextBlock HorizontalAlignment="Left" Name="StatusText" Margin="0,20" TextWrapping="Wrap" Text="{Binding StatusText}">
            ... Status ...
</TextBlock>

codebehind:

public StatusPage()
{
    InitializeComponent();
    this.DataContext = new StatusPageViewModel(this);
}

et dans viewModel:

private string _statusText;
/// <summary>
/// Status text
/// </summary>
public string StatusText
{
    get { return _statusText; }
    set { _statusText = value; }
}

et en fonction dans viewModel:

string statusText = Status.GetStatusText();
this.StatusText = statusText;

GetStatusText() renvoie une chaîne telle que "Travail effectué", etc. Les valeurs de ces fonctions sont associées au this.StatusText, mais la propriété text de TextBlock ne change pas et affiche toujours un espace réservé "... Statut ..."

Je suis au courant de questions comme celle-ci -> CLIQUEZ <--- mais après avoir lu ceci, je ne suis toujours pas en mesure de trouver une solution.

@Mettre à jour

Après vos suggestions, j'ai mis à jour mon code et j'ai maintenant ceci:

public string StatusText
{
    get 
    {
        return _statusText;
    }
    set 
    {
        _statusText = value; 
        RaisePropertyChanged("StatusText");
    }
}

et déclaration de viewModel:

 public class StatusPageViewModel : ObservableObject, INavigable

où:

La classe ObservableObject est:

public abstract class ObservableObject : INotifyPropertyChanged
{
    #region INotifyPropertyChanged Members

    /// <summary>
    /// Raises the PropertyChange event for the property specified
    /// </summary>
    /// <param name="propertyName">Property name to update. Is case-sensitive.</param>
    public virtual void RaisePropertyChanged(string propertyName)
    {
        OnPropertyChanged(propertyName);
    }

    /// <summary>
    /// Raised when a property on this object has a new value.
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// Raises this object's PropertyChanged event.
    /// </summary>
    /// <param name="propertyName">The property that has a new value.</param>
    protected virtual void OnPropertyChanged(string propertyName)
    {

        PropertyChangedEventHandler handler = this.PropertyChanged;
        if (handler != null)
        {
            var e = new PropertyChangedEventArgs(propertyName);
            handler(this, e);
        }
    }

    #endregion // INotifyPropertyChanged Members
}

Mais ça ne marche toujours pas

16
szpic

Vous devez implémenter INotifyPropertyChanged dans votre ordre ViewModel pour notifier à la vue que la propriété a été modifiée.

Voici un lien vers la page MSDN correspondante: System.ComponentModel.INotifyPropertyChanged

La chose la plus importante à noter est que vous devriez déclencher l'événement PropertyChanged dans votre créateur de propriété.

22
toadflakz

Ajouter le mode de liaison dans les deux sens, car par défaut le mode de liaison de Textblock est un moyen

<TextBlock HorizontalAlignment="Left" Name="StatusText" Margin="0,20" TextWrapping="Wrap" Text="{Binding StatusText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
            ... Status ...
</TextBlock>

et, bien sûr, vous devez implémenter INotifyPropertyChanged à cet effet, reportez-vous à ce lien pour savoir comment l’implémenter.

10
Mayur Dhingra

Lorsque vous travaillez avec des modèles de données, vous devez vous assurer que le modèle est complet au moment du chargement initial. Donc, si vous faites ceci: this.DataContext = mainViewModel et certaines parties de votre mainViewModel ne sont PAS chargées (= null), vous ne pouvez pas les lier. Exemple, j'ai un modèle dans ce modèle un objet programme. Je lie au texte d'un TextBlock à Model.Program.Name. L'objet Programme n'est pas connecté au chargement initial, vous devrez donc vous reconnecter à un objet chargé car sinon, aucune notification ne peut être envoyée.

3

Votre modèle de vue doit implémenter INotifyPropertyChanged et vous devez le soulever chaque fois que l'une de vos propriétés change (par exemple, dans le créateur). 

Sans cela, WPF n'a aucun moyen de savoir que la propriété a changé.

2
GazTheDestroyer

J'ai eu ce problème et voici ce que je faisais mal…

Remarque: j'avais codé correctement INotifyPropertyChanged.


À mon avis, j'avais

<SomeView.DataContext>
    <SomeViewModel/>
<SomeView.DataContext/>

... et cela appelle le constructeur de la VM (création d'une instance sur laquelle pointer/à laquelle être lié).

Dans une autre classe (dans le code ViewModel de la fenêtre principale de mon programme), j’étais en train d’instancier le (s) ViewModel (s), à savoir:

private SomeAstractBaseViewModel someViewModel = new SomeViewModel();
private SomeAstractBaseViewModel someOtherViewModel = new SomeOtherViewModel(); 

Ils ont tous deux hérité d'une super-classe et je basculais entre des instances affichant différentes vues dans une section de la fenêtre principale - conformément à mon intention.

Comment tout cela est câblé est une autre question, mais lorsque je supprime la problématiquexaml(en haut de cette réponse) qui instanciait auparavant une autre instance "inutilisée" du ViewModel, la vue se mettait à jour selonINotifyPropertyChangedmécanismes.

0
JohnG79