I'm new to C#/.NET and especially to binding since it is a new concept for me, I do understand simple binding like the one below...
<TextBox Name="myTextField" Text="{Binding Path=Text, ElementName=myTextField2}" />
<TextBox Name="myTextField2" Text="{Binding Path=Text, ElementName=myTextField}"/>
But I'm confused on how to do it from a ViewModel
. I was watching a video about MVVM
which helped me understand a few concepts that I had trouble understanding, but since no code was provided I tried to write the code to see the demonstration in action but I'm missing the XAML/Binding
part since the presenter doesn't show that part of the code. You can see how all works in minute 5:05
.
Here is all of the code:
Person Class:
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MVVM_BestPractices
{
public class Person : INotifyPropertyChanged
{
private string _firstName;
public string FirstName
{
get { return _firstName; }
set
{
_firstName = value;
OnPropertyChanged();
OnPropertyChanged("FullName");
}
}
private string _lastName;
public string LastName
{
get { return _lastName; }
set
{
_lastName = value;
OnPropertyChanged();
OnPropertyChanged("FullName");
}
}
public string FullName
{
get { return string.Format("{0} {1}", this.FirstName, this.LastName); }
}
public Person() {}
public Person(string firstName, string lastName)
{
this.FirstName = firstName;
this.LastName = lastName;
}
// INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
ViewModel Class:
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace MVVM_BestPractices {
public class ViewModel : INotifyPropertyChanged
{
Person _model;
public Person Model
{
get { return _model; }
set
{
_model = value;
OnPropertyChanged();
}
}
public ViewModel()
{
Model = new Person("Brian", "Lagunas");
}
// INotifyPropertyChanged
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string propertyName = "")
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
XAML Code: As you can see I have no clue on how to bind the data from the ViewModel.
<Window x:Class="MVVM_BestPractices.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MVVM_BestPractices"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:ViewModel/>
</Window.DataContext>
<Grid>
<TextBox Width="200" Height="30" Margin="158,57,159,233"/>
<TextBox Width="200" Height="30" Margin="158,102,159,188"/>
<TextBlock Text="{Binding Person, Mode=OneWay}" Width="200" Height="30" Margin="158,148,159,142"/>
</Grid>
</Window>
Can someone help me bind the data from the ViewModel to the textBoxes
as shown in minute 5:05
?
This will help me understand Binding
and MVVM
.
Without watching the video, I would say:
<TextBox Text={Binding Model.FirstName} ... />
<TextBox Text={Binding Model.LastName} ... />
<TextBlock Text="{Binding Model.FullName, Mode=OneWay}" ... />
This ought to work but only because you implemented INotifyPropertyChanged
on your Model class here. You don't always have or want that.
Side note: try to avoid using Margin=""
for layout purposes. I know that's what the Designer does but it's a really bad practice.
In your ViewModel, you call your property Model, not Person (Person being your type). So you need to change your binding to {Binding Model, Mode=OneWay}
. The binding will then happen, but you won't have the result (that I guess) you are looking for. What you want to write is not the value of Model (ie Model.ToString()), but the value of the FullName property of Model. So it's quite simple: {Binding Model.FullName, Mode=OneWay}
Moreover, in the set of your properties, you should begin with checking if the new value is different from the old one.
set
{
if (_firstName == value) return;
_firstName = value;
OnPropertyChanged();
OnPropertyChanged(nameof(FullName)); // And use nameof() like this if you're in C# 6
}
Binding to the Model property in the ViewModel is straightforward if you have set the DataContext (which you have):
<TextBlock Text="{Binding Person, Path=FirstName}"/>
or you can omit the Path:
<TextBlock Text="{Binding Person.FirstName}"/>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.