2010-05-19 4 views
3

J'utilise le modèle MVVM. J'ai unTextBox et Button - Liaison et commande

  1. zone de texte dont la propriété Text est lié à de ViewModel (VM prend en charge INotifyProperyChange) propriété Text
  2. Bouton dont la commande est liée au type de propriété ICommand de VM

Vous pouvez penser à cela comme Un SearchTextBox et SearchButton

Le problème auquel je suis confronté est que lorsque je saisis le texte dans SearchTextBox et que je clique sur SearchButton, seule l'implémentation de la propriété set liée à SearchTextBox est appelée, mais la Command pour un clic SearchButton n'exécute (Note: ICommand CanExecute handler retourne toujours vrai)

Il fonctionne très bien si je soit onglet sur SearchTextBox en utilisant la touche TAB ou utilisez la souris pour se déplacer loin de se concentrer SearchTextBox puis cliquez sur le SearchButton. Cela signifie faire deux actions séparées pour déclencher les deux événements séparément. Idéalement, un clic sur le bouton SearchButton devrait entraîner la mise au point libre de SearchTextBox, appelant ainsi la propriété Set et le clic sur le bouton Rechercher se traduit par l'exécution de la commande.

code

est comme ci-dessous

XAML:

<TextBox Text="{Binding Path=SearchText,Mode=TwoWay}"/> 

<Button Content="Search" Width="100" Command="{Binding MySearchCommand}"/> 

C#:

public String _SearchText; 
public String SearchText 
{ 
    get { return _SearchText; } 
    set 
    { 
    _SearchText = value; 
    OnPropertyChanged("SearchText"); 
    } 
} 

ICommand mise en œuvre est un implemenetation standard avec pas de code de fantaisie et CanExecute gestionnaire retourne toujours vrai

+0

comment voulez-vous que votre commande n'exécute pas lorsque votre CanExecute fonctionne? Pouvez-vous poster l'implémentation ici? (Votre méthode Execute) – Amsakanna

+1

Je pense que l'octet signifiait que CanExecute n'était pas en cours d'exécution, mais est défini pour renvoyer toujours vrai. –

+1

Il doit simplement y avoir une erreur stupide, s'il vous plaît poster votre code :) –

Répondre

0

Essayez d'isoler l'émission e en écrivant un petit projet de test qui reproduit le problème, si vous pouvez repro, s'il vous plaît poster le code. Habituellement, lorsque vous reprogrammez le problème en dehors de votre projet principal, le problème et la solution deviennent évidents.

+0

C'est ce que je fais maintenant! – byte

0

J'ai créé un exemple d'application pour reproduire ce problème.

J'ai placé le point d'arrêt et ajouté une ligne Debug.Writeline dans la propriété SearchText - Set et la méthode MySearchCommandExecute.

Lorsque des points d'arrêt sont définis, seule la propriété SearchText - Set est appelée. J'ai observé que si je supprime le point d'arrêt de la propriété SearchText - Set, la propriété et la commande sont correctement exécutées. On dirait un problème avec VS 2008 mais je peux me tromper.

Le code échantillon représentatif est comme ci-dessous

class SearchViewModel : ViewModelBase 
    { 
     public SearchViewModel() 
     { 

     } 

     public String _SearchText; 
     public String SearchText 
     { 
      get { return _SearchText; } 
      set 
      { 
       System.Diagnostics.Debug.WriteLine("Set Membership called"); 

       OnPropertyChanged("SearchText"); 
      } 
     } 

     #region Commands 
     RelayCommand _SearchCommand; 

     public ICommand SearchCommand 
     { 
      get 
      { 
       if (_SearchCommand == null) 
       { 
        _SearchCommand = new RelayCommand(param => this.MySearchCommandExecute(), param => this.MySearchCommandCanExecute); 
       } 
       return _SearchCommand; 
      } 
     } 

     public void MySearchCommandExecute() 
     { 
      System.Diagnostics.Debug.WriteLine("MySearchCommandExecute called"); 

      // Do Search 
     } 

     public bool MySearchCommandCanExecute 
     { 
      get 
      { 
       return true; 
      } 
     } 

     #endregion 
    } 

SearchView.xaml

<UserControl x:Class="WpfApplication2.SearchView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Height="300" Width="300"> 
    <StackPanel> 
     <StackPanel Orientation="Vertical" HorizontalAlignment="Left" Margin="4"> 
      <Label Foreground="Black" FontFamily="Calibri" Width="155" Margin="4,0,4,0" Content="SearchText"/> 
      <TextBox Foreground="Black" FontFamily="Calibri" Width="155" Margin="4,0,4,0" Text="{Binding Path=SearchText}"/> 
     </StackPanel> 
     <Button HorizontalAlignment="Left" Content="Search" Width="100" Command="{Binding SearchCommand}" Margin="8"/> 
    </StackPanel> 
</UserControl> 

RelayCommand.cs

// Reference: MSDN sample 
    class RelayCommand : ICommand 
    { 
     readonly Action<object> _execute; 
     readonly Predicate<object> _canExecute; 

     public RelayCommand(Action<object> execute) 
      : this(execute, null) 
     { 
     } 

     public RelayCommand(Action<object> execute, Predicate<object> canExecute) 
     { 
      if (execute == null) 
       throw new ArgumentNullException("relaycommand execute"); 

      _execute = execute; 
      _canExecute = canExecute; 
     } 

     [DebuggerStepThrough] 
     public bool CanExecute(object parameter) 
     { 
      return _canExecute == null ? true : _canExecute(parameter); 
     } 

     public event EventHandler CanExecuteChanged 
     { 
      add { CommandManager.RequerySuggested += value; } 
      remove { CommandManager.RequerySuggested -= value; } 
     } 

     public void Execute(object parameter) 
     { 
      _execute(parameter); 
     } 
    } 
0

Byte,

Désolé pour ma réponse tardive, mais j'espère Je deviendrai utile de toute façon.Je suis très occupé ces derniers temps, donc je n'ai pas pu déboguer votre code (j'essaierai de le faire quand j'aurais plus de temps), mais s'il vous plaît essayez mon exemple de code collé ci-dessous (ça marche parfaitement pour moi). Comme vous pouvez le voir, c'est extrêmement simple. J'ai utilisé votre xaml, mais pour la fenêtre:

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

     this.DataContext = new TempViewModel(); 
    } 
} 

public class TempViewModel : INotifyPropertyChanged 
{ 
    private String _searchText; 
    private ICommand _searchCommand; 

    #region Commands 

    protected class Search : ICommand 
    { 
     private TempViewModel _viewModel; 

     public bool CanExecute(object parameter) 
     { 
      return true; 
     } 

     public event EventHandler CanExecuteChanged 
     { 
      add { } 
      remove { } 
     } 

     public void Execute(object parameter) 
     { 
      //MessageBox in VM is just for demonstration 
      MessageBox.Show("command executed with search string: " + this._viewModel._searchText); 
     } 

     public Search(TempViewModel viewModel) 
     { 
      this._viewModel = viewModel; 
     } 
    } 

    #endregion //Commands 

    #region INotifyPropertyChanged 

    public event PropertyChangedEventHandler PropertyChanged; 

    public void OnPropertyChanged(String propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #endregion //INotifyPropertyChanged 

    #region Public properties 

    public String SearchText 
    { 
     get 
     { 
      return this._searchText; 
     } 
     set 
     { 
      this._searchText = value; 
      OnPropertyChanged("SearchText"); 
     } 
    } 

    public ICommand SearchCommand 
    { 
     get 
     { 
      return this._searchCommand; 
     } 
     set 
     { 
      this._searchCommand = value; 
      OnPropertyChanged("SearchCommand"); 
     } 
    } 

    #endregion //Public properties 

    public TempViewModel() 
    { 
     this.SearchCommand = new Search(this); 
     this.SearchText = "Sample string"; 
    } 
} 

N'hésitez pas à demander si vous avez d'autres questions.

EDIT: Ah, désolé, mais je changé Command="{Binding SearchCommand}"-Command="{Binding Path=SearchCommand}"