Reputation: 952
I've been working on a sample project using MVVM Light and I'm wondering how to bind a TextBox Text value and have it passed to and from the View to the View Model. This is the first time I've worked with MVVM Light so I'm new to this.
Basically a user will enter a Project name in to the Text Box name and click the New Project button which should generate a database named after what was typed in to the Project Name Text Box.
View :
<UserControl x:Class="Sample.Views.NavigationTree.NewProjectView"
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:mui="http://firstfloorsoftware.com/ModernUI"
xmlns:ignore="http://www.ignore.com"
mc:Ignorable="d ignore"
DataContext="{Binding NewProjectView, Source={StaticResource Locator}}">
<Grid>
<StackPanel Orientation="Vertical" HorizontalAlignment="Left">
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<mui:BBCodeBlock BBCode="Project Name"/>
<Label Width="10"/>
<TextBox Text="{Binding ProjName, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}" Width="120"/>
</StackPanel>
<Label Height="10"/>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Left">
<Label Width="85"/>
<Button Content="New Project" Margin="0,0,3,0" Command="{Binding AddProjectCommand}" IsEnabled="{Binding IsUserAdmin}" Grid.Column="2" Grid.Row="0"/>
</StackPanel>
</StackPanel>
</Grid>
</UserControl>
ViewModel:
using Sample.Model.Database;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using System.Text;
namespace Sample.ViewModel
{
/// <summary>
/// This class contains properties that a View can data bind to.
/// <para>
/// See http://www.galasoft.ch/mvvm
/// </para>
/// </summary>
public class NewProjectViewModel : ViewModelBase
{
private string _projName;
//Binding AddProjectCommand
public RelayCommand AddProjectCommand { get; set; }
private string consoleText { get; set; }
private StringBuilder consoleBuilder = new StringBuilder(360);
/// <summary>
/// Initializes a new instance of the NewProjectViewModel class.
/// </summary>
public NewProjectViewModel()
{
this.AddProjectCommand = new RelayCommand(() => AddProject());
}
public void AddProject()
{
ProjectDbInteraction.CreateProjectDb(_projName);
}
public string ProjName
{
get { return _projName; }
set
{
if (value != _projName)
{
_projName = value;
RaisePropertyChanged("ProjName");
}
}
}
public string ConsoleText
{
get { return consoleText; }
set
{
consoleBuilder.Append(value);
consoleText = consoleBuilder.ToString();
RaisePropertyChanged("ConsoleText");
}
}
}
}
So how do I pass the ProjName binding to and from the View to the View MOdel?
Upvotes: 2
Views: 5631
Reputation: 2469
Remove "Mode=OneWay" from your binding of the textbox where the user types the ProjName, this will allow your property to receive the value. Or choose one of the other Modes that do what you want.
OneWay: use this when you want the data in view model to modify the value in your GUI
TwoWay: use this if you want to allow view model to modify the GUI value, or if you want the GUI value changed by the user to be reflected in view model
OneTime: your view model can set the value that is shown in your GUI once, and it will never change again. Only do this if you know you're not going to need to change the value in your view model.
OneWayToSource: This is the opposite of one way -- GUI value affects view model value.
Upvotes: 1
Reputation: 2469
Looks good, you just need to create an association between the View and ViewModel. Basically, set your DataContext of your view to the ViewModel.
You can do this a few ways, i will show two: 1) In the code-behind of your view, you can create an instance of your viewmodel (ViewModel vm=new ViewModel()) as then assign it with this.DataContext=vm; 2) You can XAML Data Templates. Something like this, where Home is a view and HomeVM is viewmodel.
in
<Window
.
.
.
xmlns:HomeView="clr-namespace:Bill.Views"
xmlns:HomeVM="clr-namespace:Bill.ViewModels"
>
<Window.Resources>
<!--Home User Control and View Model-->
<DataTemplate DataType="{x:Type HomeVM:HomeVM}">
<HomeView:Home/>
</DataTemplate>
</Window.Resources>
The first seems more flexible for my normal needs...
Upvotes: 4
Reputation: 31616
Your textbox binding looks correct. What is not shown is how you associate your ViewModel to the datacontext of the page which can ultimately be consumed by the textbox. I would recommend that you do this in the code behind of the page.
public MyViewModel ModelView;
public MainWindow()
{
InitializeComponent();
DataContext = ModelView = new MyViewModel ();
}
Once the page's datacontext is set as shown above, the controls datacontext, if not set, walks up the visual tree of its parent(s) until a datacontext has been set; which is done here on the page, the ultimate parent.
I provide a more robust example on my blog article Xaml: ViewModel Main Page Instantiation and Loading Strategy for Easier Binding. which can show you how to roll your own MVVM (which is all MVVM light does).
Upvotes: 1