Reputation: 362
I am new to MVVM. I tried to create a simple program but am facing a problem. I have created a TokensViewModel
and a page. But after binding controls I found that my execution does not go to TokensViewModel
. Please tell me where I am going wrong. Here are the details:
Folder hierarchy is this way:
BusinessLogicLayer\TokenManager.cs
Commom\RelayCommand.cs
PresentationLayer\ViewModel\TokensViewModel.cs
PresentationLayer\Views\GenerateToken.xaml (Page)
ResourceAccessLayer\TokenRepository.cs
RelayCommand.cs:
class RelayCommand:ICommand
{
readonly Action<object> _execute;
readonly Predicate<object> _canExecute;
public RelayCommand() { }
public RelayCommand(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public RelayCommand(Action<object> execute): this(execute, null) {}
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);
}
}
TokenManager.cs
class TokenManager
{
public bool Add(token tokens)
{
return true;
}
}
GenerateToken.xaml
<Page x:Class="xyz.GenerateToken"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d" d:DesignHeight="800" d:DesignWidth="900"
xmlns:ViewModels="clr-namespace:xyz.PresentationLayer.ViewModel"
Title="GenerateToken">
<Grid Height="750" Width="800">
<TextBlock Height="23" HorizontalAlignment="Left" Margin="29,85,0,0" Name="lblName" Text="Name" VerticalAlignment="Top" FontSize="16" />
<TextBlock FontSize="16" Height="23" HorizontalAlignment="Left" Margin="29,154,0,0" Name="lblPlateNumber" Text="Plate Number" VerticalAlignment="Top" />
<TextBlock FontSize="16" Height="23" HorizontalAlignment="Left" Margin="29,226,0,0" Name="lblPancard" Text="Pancard Number" VerticalAlignment="Top" />
<TextBlock FontSize="16" Height="23" HorizontalAlignment="Left" Margin="410,85,0,0" Name="lblContactNumber" Text="Contact Number" VerticalAlignment="Top" />
<TextBlock FontSize="16" Height="23" HorizontalAlignment="Left" Margin="410,163,0,0" Name="lblAddres" Text="Address" VerticalAlignment="Top" Width="60" />
<Button Content="Generate" Command="{Binding SaveCommand}" Height="34" HorizontalAlignment="Left" Margin="216,328,0,0" Name="btnGenerateToken" VerticalAlignment="Top" Width="133" FontSize="20" />
<TextBox Height="32" HorizontalAlignment="Left" Margin="178,85,0,0" Text="{Binding Path=Name}" Name="txtName" VerticalAlignment="Top" Width="186" BorderThickness="2" FontSize="16" />
<TextBox BorderThickness="2" Height="32" HorizontalAlignment="Left" Text="{Binding Path=PlateNumber}" Margin="178,154,0,0" Name="txtPlateNumber" VerticalAlignment="Top" Width="186" FontSize="16" />
<TextBox BorderThickness="2" Height="32" HorizontalAlignment="Left" Text="{Binding Path=PanNumber}" Margin="178,226,0,0" Name="txtPanNumber" VerticalAlignment="Top" Width="186" FontSize="16" />
<TextBox BorderThickness="2" Height="32" HorizontalAlignment="Left" Text="{Binding Path=ContactNumber}" Margin="580,85,0,0" Name="txtContactNumber" VerticalAlignment="Top" Width="194" FontSize="16" />
<TextBlock Height="34" HorizontalAlignment="Left" Margin="29,12,0,0" Name="txtbTitle" Text="Generate Token" VerticalAlignment="Top" FontSize="22" Foreground="#FF1313D8" Width="165" />
<Button Content="Clear All" FontSize="20" Height="34" HorizontalAlignment="Left" Margin="418,328,0,0" Name="btnClearAll" VerticalAlignment="Top" Width="133" />
<TextBox Height="108" HorizontalAlignment="Left" Margin="580,166,0,0" Text="{Binding Path=Address}" Name="txtAddress" VerticalAlignment="Top" Width="194" />
</Grid>
</Page>
TokensViewModel.cs
class TokensViewModel:INotifyPropertyChanged
{
#region Private Declaration
private readonly token tokObject;
private readonly ObservableCollection<token> _token;
private readonly TokenManager tokenManager;
private readonly ICommand _SaveCommand;
ModelDataContext dataContext = new ModelDataContext();
#endregion
#region Constructor
public TokensViewModel()
{
tokObject = new token();
tokenManager = new TokenManager();
_token = new ObservableCollection<token>();
_SaveCommand = new RelayCommand(save, CanAdd);
}
#endregion
#region SaveCommand
public bool CanAdd(object obj)
{
if (Name != string.Empty && Address != string.Empty && ContactNumber.ToString() != null && PanNumber != string.Empty && PlateNumber != string.Empty)
return true;
else
return false;
}
public void save(object obj)
{
dataContext.tokens.InsertOnSubmit(new token
{
vcrNameOfCustomer = Name,
address = Address,
contact_no = ContactNumber,
pan_no = PanNumber,
plate_no = PlateNumber
});
dataContext.SubmitChanges();
}
#endregion
#region Commands
public ICommand SaveCommand { get { return _SaveCommand; } }
#endregion
#region Properties
public int Id
{
get { return tokObject.token_id; }
set
{
tokObject.token_id = value;
onPropertyChanged("Id");
}
}
public Int64 ContactNumber
{
get { return tokObject.contact_no; }
set
{
tokObject.contact_no = value;
onPropertyChanged("ContactNumber");
}
}
public string Address
{
get { return tokObject.address; }
set
{
tokObject.address = value;
onPropertyChanged("Address");
}
}
public string PanNumber
{
get { return tokObject.pan_no; }
set
{
tokObject.pan_no = value;
onPropertyChanged("PanNumber");
}
}
public string PlateNumber
{
get { return tokObject.plate_no; }
set
{
tokObject.plate_no = value;
onPropertyChanged("PlateNumber");
}
}
public string Name
{
get { return tokObject.vcrNameOfCustomer; }
set
{
tokObject.vcrNameOfCustomer = value;
onPropertyChanged("Name");
}
}
public ObservableCollection<token> tokens { get { return _token; } }
#endregion
#region INotifyProperty Members
public event PropertyChangedEventHandler PropertyChanged;
public void onPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
GenerateToken.xaml.cs
public partial class GenerateToken : Page
{
public GenerateToken()
{
InitializeComponent();
}
}
Thank you in Advance.
Upvotes: 5
Views: 6522
Reputation: 6942
You need to declare an instance of your TokensViewModel
in the XAML:
<Page ...
xmlns:ViewModels="clr-namespace:xyz.PresentationLayer.ViewModel">
<Page.Resources>
<ViewModels:TokensViewModel x:Key="ViewModel" />
</Page.Resources>
<Grid ... DataContext="{Binding Source={StaticResource ViewModel}}">
The XAML above creates an instance and adds it to the Page.Resources
dictionary with a key of ViewModel
.
Alternatively, you can set this in the code-behind if you name your Grid
:
<Grid x:Name="LayoutRoot">
public GenerateToken()
{
InitializeComponent();
LayoutRoot.DataContext = new TokensViewModel();
}
The downside of binding it in code-behind is that in many circumstances, you get Intellisense and designer support when you establish the DataContext
in the XAML. The reason for this is that the type of the DataContext
is declared in XAML at design time. In the code-behind approach, the type is not known until run-time.
The Grid.DataContext
is then bound to this instance of your TokensViewModel
. The rest of your {Binding}
in the controls within Grid
inherit the DataContext
such that you can bind with:
<TextBlock Name="lblName"
Text="{Binding Name}" />
Upvotes: 7
Reputation: 18578
You have not set the DataContext
for your page.
trying doing
DataContext = new TokensViewModel()
after InitializeComponents()
Upvotes: 1