2009-05-28 3 views
11

In meiner Ansicht habe ich eine Schaltfläche.Wie gebe ich die Informationen von View zu ViewModel mit DelegateCommand?

Wenn der Benutzer auf diese Schaltfläche klickt, möchte ich, dass das ViewModel den Kontext des TextBlock in der Datenbank speichert.

<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top"> 
    <TextBlock Text="{Binding FirstName}"/> 
    <TextBox Text="Save this text to the database."/> 
    <Button Content="Save" Command="{Binding SaveCommand}"/> 
</StackPanel> 

Doch mein DelegateCommand in meinem Ansichtsmodell, das „Save()“ Methode übergibt keine Argumente, so wie bekomme ich Daten aus der Sicht zu diesem Zeitpunkt?

#region DelegateCommand: Save 
private DelegateCommand saveCommand; 

public ICommand SaveCommand 
{ 
    get 
    { 
     if (saveCommand == null) 
     { 
      saveCommand = new DelegateCommand(Save, CanSave); 
     } 
     return saveCommand; 
    } 
} 

private void Save() 
{ 
    TextBox textBox = ......how do I get the value of the view's textbox from here?.... 
} 

private bool CanSave() 
{ 
    return true; 
} 
#endregion 

Antwort

18

Auschecken this MSDN article by Josh Smith. Darin zeigt er eine Variation von DelegateCommand, die er RelayCommand aufruft, und die Delegate Execute und CanExecute auf RelayCommand akzeptieren einen einzelnen Parameter des Typs object.

RelayCommand Verwenden Sie Informationen zu den Delegierten über eine Command passieren kann:

<Button Command="{Binding SaveCommand}" 
     CommandParameter="{Binding SelectedItem,Element=listBox1}" /> 

aktualisieren

bei this article Blick scheint es, dass es eine generische Version von DelegateCommand ist, die einen Parameter akzeptiert in ein ähnlicher Weg. Sie können versuchen, Ihren SaveCommand in einen DelegateCommand<MyObject> zu ändern und Ihre Save- und CanSave-Methoden so zu ändern, dass sie einen MyObject-Parameter annehmen.

+2

Ich löste mein Problem tatsächlich, indem ich die TextBox an eine ViewModel-Eigenschaft (INotifyPropertyChanged) gebunden habe, auf deren Wert natürlich der Save() -Befehl zugreifen kann, aber Ihre Vorschläge sind sehr interessant, werden sie auschecken. –

+0

Es gibt einen bestimmten (und einigermaßen gebräuchlichen) Anwendungsfall, bei dem Matts Lösung definitiv den Zugriff auf einen separaten gebundenen Wert gewinnt: Befehle, die von einem 'ItemsControl' ausgeführt werden. Hier kann beispielsweise ein Button in einer 'ListView' seinen' DataContext' als Parameter verwenden und das Element, auf das der Button geklickt wurde, wird zusammen mit dem Befehl übergeben. Es ist schwierig herauszufinden, auf welches der vielen Elemente der Button sonst geklickt wurde. –

+1

Beachten Sie, dass das generische 'DelegateCommand ' eine wichtige Einschränkung hat (die erst zur Laufzeit abgerufen wird - der Compiler wird sich nicht beschweren): Sie können keinen Werttyp als Parameter verwenden. Der offizielle Ratschlag ist, einen Nullwerttyp zu verwenden (was erlaubt ist) und vor der Verwendung zu prüfen, ob er einen Wert enthält (https://msdn.microsoft.com/en-us/library/gg431410%28v=pandp.50%29 .aspx - siehe Abschnitt "Bemerkungen". –

9

In Ihrer VM:

private DelegateCommand<string> _saveCmd = new DelegateCommand<string>(Save); 

public ICommand SaveCmd{ get{ return _saveCmd } } 

public void Save(string s) {...} 

In Sie anzeigen möchten, verwenden Commandparameter wie Matts Beispiel.

+0

Keine vollständige Antwort, aber dies wies mich in die richtige Richtung für die Verwendung von CommandParameter und die Angabe eines Typs für DelegateCommand. Danke – vdidxho

5

Sie fragen über die Weitergabe von Daten über die Schaltfläche Befehl.

Was Sie wirklich wollen, glaube ich, ist zu binden Ihre Textbox den Text in eine öffentliches Eigentum in Ihrem Ansichtsmodell:

<!-- View: TextBox's text is bound to the FirstName property in your ViewModel --> 
<TextBox Text="{Binding Path=FirstName}" /> 
<Button Command="{Binding SaveCommand}"/> 

<!-- ViewModel: Expose a property for the TextBox to bind to --> 
public string FirstName{ get; set; } 
... 
private void Save() 
{ 
    //textBox's text is bound to --> this.FirstName; 
} 
+0

Das ist, was ich normalerweise tue, da der TextBox-Wert bereits an eine Eigenschaft im Viewmodel gebunden ist. Es muss nicht als Parameter an den Befehl übergeben werden. –

+0

Es macht mehr Sinn (Code-Lesbarkeit), es als Parameter zu übergeben, wenn Sie den Text nur für einen Zweck verwenden. Wie zum Beispiel die Weitergabe des Aktivierungsschlüssels an Ihre VM. –

12

hier ist die elegante Art und Weise.

einen Namen Ihrer Textbox geben, dann die Commandparameter in der Schaltfläche binden, um es Text-Eigenschaft ist:

<StackPanel HorizontalAlignment="Left" VerticalAlignment="Top"> 
    <TextBlock Text="{Binding FirstName}"/> 
    <TextBox x:Name="ParameterText" Text="Save this text to the database."/> 
    <Button Content="Save" Command="{Binding SaveCommand}" 
      CommandParameter="{Binding Text, ElementName=ParameterText}"/> 
</StackPanel> 
1

ich nicht erlaubt bin Kommentare vorhanden zu machen, denke ich. Ich antworte auf Carlos Vorschlag, weil ich es ausprobiert habe. Während es eine großartige Idee ist, müsste DelegateCommand in irgendeiner Weise geändert werden, da sonst der folgende Fehler angezeigt wird: Ein Feldinitialisierer kann nicht auf das nicht statische Feld, die Methode oder die Eigenschaft 'MyViewModel.Save (string)' verweisen.

Verwandte Themen