2012-05-31 16 views
9

Ho una vista WPF con un controllo TextBox, che lega il campo di testo a un ViewModel con UpdateSourceTrigger impostato su PropertyChanged. Nel setter proprietà nel ViewModel, ho un semplice controllo per evitare che il testo superi 10 caratteri:WPF - MVVM - Casella di testo che non viene sincronizzata con la proprietà viewmodel

<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}" /> 

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 

     this.DataContext = new MainViewModel(); 
    } 
} 


public string Name 
{ 
    get { return _Name; } 
    set 
    { 
     if (_Name != value) 
     { 
      if (value.Length <= 10) 
      { 
       _Name = value; 
      } 
      RaisePropertyChanged("Name"); 
     } 
    } 
} 

Se il valore non è impostato, ho ancora RaisePropertyChanged (che spara semplicemente PropertyChanged).

Il problema è che quando digito l'undicesimo carattere nell'interfaccia utente, non aggiorno _Name. Sparo PropertyChanged, e posso vedere il get accessor ottenere chiamato e restituisce la stringa con solo 10 caratteri. Tuttavia, il mio TextBox non riflette questo; mostra ancora la stringa con 11 caratteri.

Inoltre, se sull'undicesimo carattere cambio il testo nel setter su "ERRORE", e la proprietà del fuoco cambia, il TextBox esegue l'aggiornamento per mostrare il testo modificato.

Quindi, perché se modifica il testo del setter sul valore precedente, l'interfaccia utente non riflette questo?

So che esistono altri modi di gestire i caratteri massimi, ma perché non funziona?

risposta

22

Questo non è altro che un bug nel framework. La proprietà Text nello TextBox ottiene il nuovo valore ma la GUI non è più sincronizzata con il proprio TextProperty. Questo vale anche per qualsiasi ItemsControl quando si desidera annullare una modifica di SelectedItem dal ViewModel ed è davvero fastidioso.

Questo errore non si verifica quando si utilizza esplicitamente Binding, quindi è possibile utilizzarlo come soluzione alternativa.

Xaml

<TextBox Text="{Binding Path=MyName, 
         UpdateSourceTrigger=Explicit}" 
     TextChanged="TextBox_TextChanged"/> 

codice dietro

private void TextBox_TextChanged(object sender, TextChangedEventArgs e) 
{ 
    TextBox textBox = sender as TextBox; 
    textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource(); 
} 

Per verificare che l'interfaccia grafica TextBox in effetti non è sincronizzata, basta osservare il valore di TextBox.Text. Il TextBox dirà "123456789___0" ad esempio mentre TextBlock dice "123456789".

<StackPanel> 
    <TextBox Name="myTextBox" 
      Text="{Binding Path=MyName, 
          UpdateSourceTrigger=PropertyChanged}"/> 
    <TextBlock Text="{Binding ElementName=myTextBox, Path=Text}"/> 
</StackPanel> 
+0

Grazie! Qualche idea se questo è stato segnalato alla nave madre? Se no, lo farò. –

+0

@SteveOsborn: Haha, non sono sicuro se questo è stato segnalato alla nave madre :) Ho guardato prima ma non ho trovato nulla ma è un po 'difficile sapere cosa cercare esattamente. Vai avanti e segnalalo, fammi sapere quando lo hai e lo invierò. –

+0

https://connect.microsoft.com/VisualStudio/feedback/details/745368/wpf-textbox-binding-doesnt-work-properly –

Problemi correlati