Click here to Skip to main content
15,867,594 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am beginner in MVVM, my problem is i am not able to access MainWindow(View) textBox value in ViewModel.

What I have tried:

This is Model properties
<pre> public class ModelEntity:INotifyPropertyChanged
    {
        public ModelEntity()
        { }
        private string _firstname;
        private string _lastName;
        private string _address;
        private string _contact;
        private string _dedscription;

        public string FirstName { get { return _firstname; } set { _firstname = value;OnPropertyChanged("FirstName"); } }
        public string LastName { get { return _lastName; } set { _lastName = value; OnPropertyChanged("LastName"); } }
        public string Address { get { return _address; } set { _address = value; OnPropertyChanged("Address"); } }
        public string Contact { get { return _contact; } set { _contact = value; OnPropertyChanged("Contact"); } }
        public string Description { get { return _dedscription; } set { _dedscription = value; OnPropertyChanged("Description"); } }

        public event PropertyChangedEventHandler PropertyChanged;
        public void OnPropertyChanged(string PropertyName)
        {
            if(PropertyChanged!=null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
            }
        }
    }

Below is ViewModel Code
public  class ViewModel
 {
     MyDemoServiceReference.ModelEntity objentity;
     public ObservableCollection<Model.ModelEntity> obsColl { get; set; }
     MyDemoServiceReference.MyDemoServiceClient objservice = new MyDemoServiceReference.MyDemoServiceClient();
     public ModelEntity objmodel { get; set; }
     public ViewModel()
     {
        // obsColl = new ObservableCollection<ModelEntity>();
         // objentity = new MyDemoServiceReference.ModelEntity();
         objmodel = new ModelEntity();
         AddUser = new RelayCommand(SaveData);
     }
     public RelayCommand AddUser { get; set; }
     public RelayCommand UpdateUser { get; set; }



     void SaveData(object parameter)
     {

         // ModelEntity objmodel = new ModelEntity();
         // MyDemoServiceReference.ModelEntity objentity = new MyDemoServiceReference.ModelEntity();

         objentity.FirstName = objmodel.FirstName;
         if (objservice.SaveData(objentity))
             MessageBox.Show("Data Inserted");
         else
             MessageBox.Show("Data Not Inserted");

     }
 }


Below is Xmal Code

<Window x:Class="WPFDemo.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:Model="clr-namespace:WPFDemo.Model"
        xmlns:viewmodel="clr-namespace:WPFDemo.ViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
 
    <Border Background="Chocolate" BorderThickness="1">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
            <TextBox Grid.Row="0" Height="50" Width="150" Text="{Binding ModelEntity.FirstName ,Mode=TwoWay}"  Grid.Column="1"></TextBox>
            <TextBox Grid.Row="1" Height="50" Width="150" Text="{Binding ModelEntity.LastName,Mode=TwoWay}" Grid.Column="1"></TextBox>
            <TextBox Grid.Row="2" Height="50" Width="150" Text="{Binding ModelEntity.Address,Mode=TwoWay}" Grid.Column="1"></TextBox>
            <TextBox Grid.Row="3" Height="50" Width="150" Text="{Binding ModelEntity.Contact,Mode=TwoWay}" Grid.Column="1"></TextBox>
            <TextBox Grid.Row="4" Height="50" Width="150" Text="{Binding ModelEntity.Description,Mode=TwoWay}" Grid.Column="1"></TextBox>
            <Label Grid.Row="0" Height="50" Width="150" Content="FirstName" Grid.Column="0"></Label>
            <Label Grid.Row="1" Height="50" Width="150" Content="LastName" Grid.Column="0"></Label>
            <Label Grid.Row="2"  Height="50" Width="150" Content="Address" Grid.Column="0"></Label>
            <Label Grid.Row="3" Height="50" Width="150" Content="Contact" Grid.Column="0"></Label>
            <Label Grid.Row="4"  Height="50" Width="150" Content="Description" Grid.Column="0"></Label>
            <Button Content="Save" Grid.Row="5" Grid.Column="2" Command="{Binding Path=AddUser}"  Height="50" Width="100"></Button>
        </Grid>
   </Border>
</Window>
Posted
Updated 9-Jan-17 7:22am
v2
Comments
Kenneth Haugland 7-Jan-17 2:21am    
Am I blind, or did you forget to set the DataContext?
Member 10310320 7-Jan-17 2:42am    
Here it is
namespace WPFDemo
{
/// <summary>
/// Interaction logic for MainWindow.xaml
///
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.DataContext = new ViewModel.ViewModel();

}
}
}
Kenneth Haugland 7-Jan-17 3:27am    
Well, that is correct, but what are you really complaining about here? Normally I would have sent some CommandParameters with the button click, is that what you are asking about?
Member 10310320 7-Jan-17 4:15am    
In this function
void SaveData(object parameter)
{

// ModelEntity objmodel = new ModelEntity();
// MyDemoServiceReference.ModelEntity objentity = new MyDemoServiceReference.ModelEntity();

objentity.FirstName = objmodel.FirstName;
if (objservice.SaveData(objentity))
MessageBox.Show("Data Inserted");
else
MessageBox.Show("Data Not Inserted");

}
I am not getting textbox value i.e FirstName
or various control as well
#realJSOP 7-Jan-17 18:00pm    
Seriously? You down-voted the only answer you got so far from someone with more years of WPF experience than you have in the industry?

First, your MVVM construct is ass-backwards. It should be more like this:

C#
public class Model
{
    public string Prop1 { get; set; }

    public Model()
    {
    }

    public void GetData()
    {
        try
        {
            // retrieve the data from the datasource
            // populate this object with the retrieved data
        }
        catch (Exception ex)
        {
            // handle exception here
        }
    }

    public void SaveData
    {
        try
        {
            // save the data to the datasource
        }
        catch (Exception ex)
        {
            // handle exception here
        }
    }
}

public class ViewModel : INotifyPropertyChanged, IDataErrorInfo
{
    // INotifyPropertyChanged implementation code goes here

    // IDataErrorInfo code goes here

    private string prop1;

    public string Prop1 
    { 
        get { return this.prop1; }
        set
        {
            if (value != this.prop1)
            {
                this.prop1 = value;
                this.NotifyPropertyChanged();
            }
        }
    }

    public ViewModel()
    {
        Model model = new Model();
        model.GetData();
        this.Prop1 = model.prop1;
    }
}


public class Window
{
    public ViewModel vm { get; set; }

    public Window()
    {
        this.InitializeComponents();
        this.DataContext = this;
        this.vm = new ViewModel();
    }
}


At that point, you can bind to vm.Prop1 in your XAML.

Here's a handy class that I wrote and use all the time that inherits from both INotifyPropertyChanged and IDataErrorInfo. I wrote it to be compatible with new and older versions of .Net. This should ease the pain a little of implementing ViewModel classes. Just inherit it in your own objects.

using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WpfCommon
{
	/// <summary>
	/// Base class for all objects that require notifiablity and data validation
	/// </summary>
	public class Notifiable : INotifyPropertyChanged, IDataErrorInfo
	{
		#region INotifyPropertyChanged

		/// <summary>
		/// Occurs when a property value changes.
		/// </summary>
		public event PropertyChangedEventHandler PropertyChanged;

#if _NET_45_
		/// <summary>
		/// Notifies that the property changed, and sets IsModified to true.
		/// </summary>
		/// <param name="propertyName">Name of the property.</param>
        protected void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
				if (propertyName != "IsModified")
				{
					this.IsModified = true;
				}
            }
        }
#else
		/// <summary>
		/// Notifies that the property changed, and sets IsModified to true.
		/// </summary>
		/// <param name="propertyName">Name of the property.</param>
        protected virtual void NotifyPropertyChanged(String propertyName = "")
        {
            if (this.PropertyChanged != null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
				if (propertyName != "IsModified")
				{
					this.IsModified = true;
				}
            }
        }
#endif
		#endregion INotifyPropertyChanged

		#region IDataErrorInfo Code

		/// <summary>
		/// Gets an error message indicating what is wrong with this object.
		/// </summary>
		public string Error
		{
			get { return "Error"; }
		}

		/// <summary>
		/// Gets the error message for the property with the given name.
		/// </summary>
		/// <param name="columnName">Name of the column.</param>
		/// <returns>The generated error message (if any).</returns>
		public string this[string columnName]
		{
			get 
			{
				return Validate(columnName);
			}
		}

		/// <summary>
		/// Validates the specified propery.
		/// </summary>
		/// <param name="properyName">Name of the propery.</param>
		/// <returns>Empty string if valid, otherwise, appropriate error message.</returns>
		protected virtual string Validate(string propertyName)
		{
			//Retun error message if there is error, otherwise return empty string
			string validationMsg = string.Empty;
			return validationMsg;
		}

		#endregion IDataErrorInfo Code

		#region Fields

		private bool isModified;
		private bool isSelected;
		private bool isVisible;
		private bool isEnabled;
		private bool isNew;
		private bool isClone;
		private bool isDeleted;
		private bool isValid;

		#endregion Fields

		#region Properties

		/// <summary>
		/// Gets or sets a value indicating whether this instance is modified.
		/// </summary>
		public virtual bool IsModified
		{
			get { return this.isModified; }
			set
			{
				if (this.isModified != value)
				{
					this.isModified = value;
					this.NotifyPropertyChanged("IsModified");
				}
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether this instance is selected.
		/// </summary>
		public virtual bool IsSelected
		{
			get { return this.isSelected; }
			set
			{
				if (this.isSelected != value)
				{
					this.isSelected = value;
					this.NotifyPropertyChanged("IsSelected");
				}
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether this instance is visible.
		/// </summary>
		public virtual bool IsVisible
		{
			get { return this.isVisible; }
			set
			{
				if (value != this.isVisible)
				{
					this.isVisible = value;
					this.NotifyPropertyChanged("IsVisible");
				}
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether this instance is enabled.
		/// </summary>
		public virtual bool IsEnabled
		{
			get { return this.isEnabled; }
			set
			{
				if (value != this.isEnabled)
				{
					this.isEnabled = value;
					this.NotifyPropertyChanged("IsEnabled");
				}
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether this instance is new.
		/// </summary>
		public virtual bool IsNew
		{
			get { return this.isNew; }
			set
			{
				if (value != this.isNew)
				{
					this.isNew = value;
					this.NotifyPropertyChanged("IsNew");
				}
			}
		}

		/// <summary>
		/// Gets or sets a value indicating whether this instance is a clone of an existing object.
		/// </summary>
		public virtual bool IsClone
		{
			get { return this.isClone; }
			set
			{
				if (value != this.isClone)
				{
					this.isClone = value;
					this.NotifyPropertyChanged("IsClone");
				}
			}
		}
		/// <summary>
		/// Get/set the flag indicating whether or not this item is marked for delete.
		/// </summary>
		public virtual bool IsDeleted
		{
			get { return this.isDeleted; }
			set
			{
				if (value != this.isDeleted)
				{
					this.isDeleted = value;
					this.NotifyPropertyChanged("IsDeleted");
				}
			}
		}

		/// <summary>
		/// Get or set a flag indicating whether or not this item has an error
		/// </summary>
		public virtual bool IsValid
		{
			get { return this.isValid; }
			set
			{
				if (value != this.isValid)
				{
					this.isValid = value;
					this.NotifyPropertyChanged("IsValid");
				}
			}
		}

		#endregion Properties

		#region Constructor

		/// <summary>
		/// Initializes a new instance of the <see cref="Notifiable"/> class.
		/// </summary>
		public Notifiable(bool isNew=false)
		{
			this.IsNew      = isNew;
			this.IsModified = false;
			this.IsVisible  = true;
			this.IsEnabled  = true;
			this.isValid    = true;
			this.IsClone    = false;
			this.IsDeleted  = false;
		}

		#endregion Constructor
	}
}
 
Share this answer
 
Let's try it this way.

0) The model is not supposed to have notification code in it. It's only supposed to load and save the data. That's it.

1) The view model is where you interface the data in the model with the view. It's responsible for manipulating the data into a form that makes it easier for the view to use. The view model should inherit the INotifyPropertyChanged interface, and implement the required methods and properties. Optionally, it should also inherit the IDataErrorinfo interface, but is only necessary if you want to perform validation. Your UI should bind to the view model.

2) When you instantiate your view model in the form/control, make sure you define it as public. If you don't, binding *will not* work.

3) Don't forget to set your DataContext in the form/control. Most of the time, I simply set this.DataContext = this in the constructor of the form/control. You can also set the DataContext element of a individual controls in the form, but that's a pain and can be difficult to maintain.

4) I provided a class in my previous answer that you can inherit that does all the nasty work of INotifyPropertyChanged without having to clutter your view model classes. You can also inherit the class with UI elements.

5) I recommend that you refactor your code to follow the best practice I outlined in my first answer. You will find it much easier to separate concerns, and it will keep you from having to post questions here about simple concepts.
 
Share this answer
 
Comments
Member 10310320 9-Jan-17 9:57am    
This is My model Code
public class ModelEntity:INotifyPropertyChanged
{
public ModelEntity()
{ }
private string _firstname;
private string _lastName;
private string _address;
private string _contact;
private string _dedscription;

public string FirstName { get { return _firstname; } set { _firstname = value;PropertyChang("FirstName"); } }
public string LastName { get { return _lastName; } set { _lastName = value; PropertyChang("LastName"); } }
public string Address { get { return _address; } set { _address = value; PropertyChang("Address"); } }
public string Contact { get { return _contact; } set { _contact = value; PropertyChang("Contact"); } }
public string Description { get { return _dedscription; } set { _dedscription = value; PropertyChang("Description"); } }

public event PropertyChangedEventHandler PropertyChanged;
public void PropertyChang(string PropertyName)
{
if(PropertyChanged!=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
}
}
}
I got solution..
public  class EmpViewModel: INotifyPropertyChanged
   {
       MyDemoServiceReference.ModelEntity objentity;
       private ObservableCollection<Model.ModelEntity> obsColl { get; set; }
       MyDemoServiceReference.MyDemoServiceClient objservice = new MyDemoServiceReference.MyDemoServiceClient();
       public ModelEntity objmodel { get; set; }
       public EmpViewModel()
       {
           AddUser = new Command(AddCanExuteMethod, AddExuteMethod);
           obsColl = new ObservableCollection<Model.ModelEntity>();
           // objentity = new MyDemoServiceReference.ModelEntity();
           objmodel = new ModelEntity();

       }
       public ICommand AddUser { get; set; }
       public ICommand UpdateUser { get; set; }
     public ObservableCollection<Model.ModelEntity> Objmodel
       {
           get
           {
               return obsColl;
           }
           set
           {
               obsColl = value;
               OnPropertyChanged("Objmodel");
           }
       }
       public bool AddCanExuteMethod(object parameter)
       {
           return true;
       }
       public void AddExuteMethod(object parameter)
       {
           objentity = new MyDemoServiceReference.ModelEntity();
           objentity.FirstName = objmodel.FirstName;
           if (objservice.SaveData(objentity))
           {
               MessageBox.Show("Data Inserted");

           }
           else
           {
               MessageBox.Show("Data Not Inserted");
           }


       }
       void SaveData(object parameter)
       {


           // ModelEntity objmodel = new ModelEntity();
           // MyDemoServiceReference.ModelEntity objentity = new MyDemoServiceReference.ModelEntity();

           objentity.FirstName = objmodel.FirstName;
           if (objservice.SaveData(objentity))
               MessageBox.Show("Data Inserted");
           else
               MessageBox.Show("Data Not Inserted");

       }

       public event PropertyChangedEventHandler PropertyChanged;
       public void OnPropertyChanged(string PropertyName)
       {
           if (PropertyChanged != null)
           {
               PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
           }
       }
   }


My Xaml Code is
<Window x:Class="WPFDemo.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:WPFDemo.Model"
        xmlns:viewmodelVm="clr-namespace:WPFDemo.ViewModel"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    
<Border Background="Chocolate" BorderThickness="1">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
            <TextBox Grid.Row="0" Height="50" Width="150" Text="{Binding objmodel.FirstName ,Mode=TwoWay}"  Grid.Column="1"></TextBox>
            <TextBox Grid.Row="1" Height="50" Width="150" Text="{Binding objmodel.LastName,Mode=TwoWay}" Grid.Column="1"></TextBox>
            <TextBox Grid.Row="2" Height="50" Width="150" Text="{Binding objmodel.Address,Mode=TwoWay}" Grid.Column="1"></TextBox>
            <TextBox Grid.Row="3" Height="50" Width="150" Text="{Binding objmodel.Contact,Mode=TwoWay}" Grid.Column="1"></TextBox>
            <TextBox Grid.Row="4" Height="50" Width="150" Text="{Binding Description,Mode=TwoWay}" Grid.Column="1"></TextBox>
            <Label Grid.Row="0" Height="50" Width="150" Content="FirstName" Grid.Column="0"></Label>
            <Label Grid.Row="1" Height="50" Width="150" Content="LastName" Grid.Column="0"></Label>
            <Label Grid.Row="2"  Height="50" Width="150" Content="Address" Grid.Column="0"></Label>
            <Label Grid.Row="3" Height="50" Width="150" Content="Contact" Grid.Column="0"></Label>
            <Label Grid.Row="4"  Height="50" Width="150" Content="Description" Grid.Column="0"></Label>
            <Button Content="Save" Grid.Row="5" Grid.Column="2" Command="{Binding Path=AddUser}"  Height="50" Width="100"></Button>
        </Grid>
   </Border>
</Window>
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900