xamarin Binding To List - c#

I'm new to Xamarin and C#, so forgive me if my code is crap.
So essentially I'm trying to create a simple page that displays a list of course names, and allows a button to insert or remove items from the list within the view.
As of now the program builds and runs but the view does not display the contents of the list. Any help would be greatly appreciated. Thanks!
Here's the view:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="65" />
<RowDefinition Height="*"/>
<RowDefinition Height="50" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Frame OutlineColor="Black" Grid.Row="0" Grid.ColumnSpan="2">
<Label Text= "My Courses" FontSize="20" TextColor="Black" HorizontalTextAlignment="Center"/>
</Frame>
<Frame OutlineColor="Black" Grid.Row="1" Grid.ColumnSpan="2">
<ListView x:Name="CourseList" ItemsSource="{Binding GetCourseList}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>
<Label FontSize="14" Text="{Binding Name}" TextColor="Black" Grid.Row="0" Grid.Column="0"/>
<Button FontSize="14" Text="X" TextColor="Black" Grid.Row="0" Grid.Column="1"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Frame>
<Button Text="+" FontSize="20" TextColor="Green" BackgroundColor="Silver"
HorizontalOptions="Fill" VerticalOptions="Center"
Grid.Row="2" Grid.ColumnSpan="2"
/>
</Grid>
Here's the View.cs code:
public partial class MainPage : ContentPage
{
MainPageViewModel vm;
public MainPage()
{
vm = new MainPageViewModel();
vm.AddCourse();
BindingContext = vm;
InitializeComponent();
}
Here's the View Model:
class MainPageViewModel
{
public string Name { get; set; }
public List<Course> Courses;
public MainPageViewModel()
{
Courses = new List<Course>();
}
public List<Course> GetCourseList()
{
return Courses;
}
public void AddCourse()
{
Course NewCourse = new Course();
NewCourse.Name = "New Course Added";
Courses.Add(NewCourse);
}
}
Finally, Here's my Model:
public class Course
{
public string Name { get; set; }
}
So I have been able to display a list using this code but I do not believe this will allow me to add or delete from the list and update the view via button click (Correct me if I'm wrong).
public List<Course> Courses{
get{
return new List<Course>(){
new Course(){Name = "Added a course"}
};
}

I think I just found my error and solution.
public List<Course> Courses{
get{
return new List<Course>(){
new Course(){Name = "Added a course"}
};
}
Because Courses is "read only" and now being bound to the view I created a member variable List VMCourse to hold the actually list of objects and am using Courses to be bounded to and read into the view.
It appears to work, but I still need to test it with button features for adding and deleting from the list. Does this look like a decent solution to you guys?
Thanks in advance!
class MainPageViewModel
{
public string Name { get; set; }
public List<Course> VMCourse;
//This is now bound to the view's listview
public List<Course> Courses {
get
{
return VMCourse;
}
}
public MainPageViewModel()
{
VMCourse = new List<Course>();
}
public void AddCourse()
{
Course NewCourse = new Course();
NewCourse.Name = "New Course Added";
VMCourse.Add(NewCourse);
}

You cannot bind a list to a method. You should use binding with properties. So to fix this you only need to change
public List<Course> GetCourseList()
{
return Courses;
}
To
public List<Course> GetCourseList
{
get { return Courses; }
}
But, as it's mentioned in the comments not any property is suitable to be used with binding unless you know what you are doing so search about binding.

Related

Update the object of ObservableCollection is not reflecting the in the UI

I am binding ObservableCollection with CollectionView.
<CollectionView ItemsSource="{Binding LeftExercises}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:ExerciseModel">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*" />
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="4*" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Text="{Binding SetNumber}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" FontSize="Medium" />
<Label Grid.Column="1" Grid.Row="0" Text="{Binding Weight}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" FontSize="Medium" />
<Label Grid.Column="2" Grid.Row="0" Text="{Binding Reps}" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" TextColor="Black" FontSize="Medium" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
private ObservableCollection<ExerciseModel> _leftExercises;
public ObservableCollection<ExerciseModel> LeftExercises
{
get => _leftExercises;
set
{
if (_leftExercises != value)
{
_leftExercises = value;
OnPropertyChanged(nameof(LeftExercises));
}
}
}
When I add a new object to the Collection, it will reflect in my UI but whenever I try to update the value of any object, it will not reflect.
This is my model
public class ExerciseModel
{
public int SetNumber { get; set; }
public decimal Weight { get; set; }
public int Reps { get; set; }
public ExerciseType ExerciseType { get; set; }
public Side Side { get; set; }
}
I am incrementing the Reps (update Reps property) from the below command.
private Command _dummyLeftIncreaseRepsCommand;
public Command dummyLeftIncreaseRepsCommand
{
get
{
return _dummyLeftIncreaseRepsCommand ??= new Command(() =>
{
ExerciseModel lastObj = LeftExercises.Last(x => x.Side == SharedVM.ActiveSide);
lastObj.Reps += 1;
});
}
}
Your ExerciseModel class needs to implement INotifyPropertyChanged.
To do so, simply add the interface name to your class code, like this:
class MyClass : INotifyPropertyChanged
Alternatively, you can set the ItemsSource for the object again. Doing so will update the visual as well. You can do this at runtime like this:
XAML file:
<CollectionView x:Name="MyView">[...]
Code in background:
MyView.ItemsSource = MyCollectionVar;
I advise you to use CommunityToolkit.MVVM and CommunityToolkit.MAUI, when you try to bind commands, observable properties and collections to your XAML.
The benefit of this will be that you wont have to write walls of code, and spend hours to figure out why it is not working.
It saves you time, that you can put in something useful, instead of dealing with boilerplate code.

No Data Context Found for Binding Recipes

I'm having a problem on how to display my binding context, i have it on my code behind but its not working. it says no data context found
I tried other methods but it still doesn't read my binding. Here is my xaml code
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="App1.RecipePage1"
Title="Recipe Name">
<ContentPage Title="Ingredients">
<StackLayout>
<ListView ItemsSource="{Binding Recipes}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Frame>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding Ingredient}"></Label>
<Label Grid.Row="0" Grid.Column="1" Text="{Binding Quantity}"></Label>
</Grid>
</Frame>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage>
And this is my code behind
public partial class RecipePage1 : TabbedPage
{
public IList<Recipe> Recipes { get; set; }
public RecipePage1()
{
InitializeComponent();
Recipes = new List<Recipe>();
Recipes.Add(new Recipe() { Ingredient = "Kimchi", Quantity = "100 Grams" });
Recipes.Add(new Recipe() { Ingredient = "Noodle", Quantity = "80 Grams" });
Recipes.Add(new Recipe() { Ingredient = "Scallions", Quantity = "150 Grams" });
Recipes.Add(new Recipe() { Ingredient = "Spinach", Quantity = "200 Grams" });
Recipes.Add(new Recipe() { Ingredient = "Prawns", Quantity = "500 Grams" });
BindingContext = this;
}
public class Recipe
{
public string Ingredient { get; set; }
public string Quantity { get; set; }
}
}
there is no error, it will run but it doesnt read my binding even if i already called it on my behind
It is a simple binding problem. If you want to use the binding in the xaml, you need to use the MVVM to set a ViewModel which implements the INotifyChanged interface as the binding context. You can check the official document about it.
In addition, you can also give the ListView a name such as:
<ListView x:Name = "listview">
And set the ItemSource in the page such as:
listview.ItemSource = Recipes;
You can check the official document about the ListView.

Xamarin Forms ListView grouping bind issue

I have been trying to play around Xamarin Forms for a while and then came across to the Listview Grouping. I am not getting done its showing blank list. Please give me help to find where I am going wrong? Thanks in advance
However, My class domain looks like:
public class LineItemTaxDto
{
public int InvoiceLineItemId { get; set; }
public int InvoiceId { get; set; }
public int TaxId { get; set; }
public decimal TaxRate { get; set; }
public decimal TaxAmount { get; set; }
public string TaxName { get; set; }
}
My View Model property look like
public IEnumerable<KeyValuePair<string, ObservableCollection<LineItemTaxDto>>> ReceiptTaxList { get; set; }
My expecting result look like:
My xaml code below
<ListView x:Name="TaxListView"
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
ItemsSource="{Binding Invoice.ReceiptTaxList}"
IsGroupingEnabled="true">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Key}" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Label Text="{Binding TaxName}" Grid.Row="0" Grid.Column="0" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" HorizontalTextAlignment="End" Margin="0,5,0,5" />
<Label Grid.Row="0" Grid.Column="1" Text="{Binding TaxAmount, Converter={Helpers:CurrencyAmountConverter}}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" Margin="0,5,0,5" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
EDIT
I am set value in view will appear method
Invoice.ReceiptTaxList = Invoice.InvoiceLineItems.Select(x => { return new KeyValuePair<string, ObservableCollection<LineItemTaxDto>>(x.TaxName, x.LineItemTaxes); });
The value was set properly
I have solved this tricky code not using grouping but now its work as expected
My ViewModel Code
var TaxList = Invoice.InvoiceLineItems.Where(x => x.TaxId > 1).GroupBy(y=>y.TaxId > 1).Select(x =>
{
return new KeyValuePair<LineItemTaxDto, ObservableCollection<LineItemTaxDto>>(new LineItemTaxDto()
{
InvoiceLineItemId = x.First().Id,
InvoiceId = x.First().InvoiceId,
TaxId = x.First().TaxId,
TaxRate = x.First().TaxRate,
TaxAmount = x.Sum(a=>a.TaxAmount),
TaxName = taxlabel + " (" + x.First().TaxName + ")"
}, x.First().LineItemTaxes);
});
var taxes = new ObservableCollection<LineItemTaxDto>();
foreach (var tax in TaxList.GroupBy(tax => tax.Key.TaxId).Select(grp => grp.First()))
{
taxes.Add(tax.Key);
foreach (var subtax in tax.Value.Where(x => x.TaxId > 0))
{
taxes.Add(subtax);
}
}
Invoice.ReceiptTaxList = taxes;
My Xaml Code
<ListView
x:Name="TaxListView"
ItemsSource="{Binding Invoice.ReceiptTaxList}"
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
SeparatorVisibility="None"
HasUnevenRows="false"
RowHeight="35"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding TaxName}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" HorizontalTextAlignment="End" Margin="0,5,0,5" />
<Label Grid.Row="0" Grid.Column="1" Text="{Binding TaxAmount, Converter={Helpers:CurrencyAmountConverter}}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" Margin="0,5,0,5" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
You must use a list of list as items source on listview to get it working. I recommend you to create a class with the properties you want to show at header like this:
public class TaxesObservableCollection<T> : ObservableCollection<T> // Think about to implement INotifyPropertyChanged too, I guess it will be usefull
{
public TaxesObservableCollection(IEnumerable<T> collection, string taxGroupName) : base(collection)
{
TaxGroupName = taxGroupName;
}
private bool taxGroupName;
public bool TaxGroupName
{
get { return taxGroupName; }
set { taxGroupName = value; }
}
}
In your view model:
public IEnumerable<TaxesObservableCollection<LineItemTaxDto>> ReceiptTaxList { get; set; }
Your ListView:
(...) // The rest of it as you did
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding TaxGroupName}" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
(...) // The rest of it as you did
And you fill it this way:
Invoice.ReceiptTaxList = Invoice.InvoiceLineItems.Select(x => { return new TaxesObservableCollection<LineItemTaxDto>(x.LineItemTaxes, x.TaxName); }).ToList();
It should works, please let me know if is that what you wanted.

Put data from JSON file in a listview and bind them to a grid in xaml

I have a DetailPage where I have put a ContenView into. In this ContenView I implemented a Grid because I wanted something like Refresh-Button for the JSON-ListView. That worked really well so far.
With your help I've accomplished to parse the JSON Data and put it into a ListView. My plan was to put this ListView in the 2nd row of my first Grid. I did another Grid in the first Grid where I tried to push the ListView inside, but the fields are empty...
Screenshot: http://imgur.com/a/Tj0kd
Here is my XAML Code from the DetailPage
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ODC_Foto_ConWin_v1.YardList"
xmlns:local="clr-namespace:ODC_Foto_ConWin_v1"
Title="YardList"
BackgroundColor="LightGray">
<ContentPage.Content>
<Grid BackgroundColor="#004d93">
<Grid.RowDefinitions>
<RowDefinition Height="30"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<Label Grid.Column="0" Grid.Row="0" Text="File-Age: < 12m" FontSize="Small" Margin="5,5,0,0" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" HorizontalOptions="Start" VerticalOptions="Center" TextColor="White" FontAttributes="Bold"/>
<Image Source="sync.png" Grid.Column="1" Grid.Row="0" Scale="0.7" HorizontalOptions="End" VerticalOptions="Center" Margin="0,5,0,0"/>
<Label Grid.Column="2" Grid.Row="0" Text="Sync" FontSize="Small" HorizontalTextAlignment="Center" VerticalTextAlignment="Center" HorizontalOptions="End" VerticalOptions="Center" TextColor="White" Margin="0,5,5,0" FontAttributes="Bold"/>
<Button Grid.Column="1" Grid.Row="0" Grid.ColumnSpan="2" BackgroundColor="Transparent" VerticalOptions="Center" Clicked="yardListSyncButton_Clicked"/>
<Grid Grid.ColumnSpan="3" Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListView x:Name="listViewJson">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Grid.Column="0" Text="{Binding id}" BackgroundColor="Transparent" />
<Label Grid.Column="1" Text="{Binding kfz_nr}" BackgroundColor="Transparent" />
<Label Grid.Column="2" Text="{Binding kfz_kz}" BackgroundColor="Transparent" />
<Label Grid.Column="3" Text="{Binding timestamp}" BackgroundColor="Transparent" />
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
<ActivityIndicator x:Name="ProgressLoader" IsVisible="True" IsRunning="True"/>
</Grid>
</ContentPage.Content>
<ContentPage.ToolbarItems>
<ToolbarItem Icon="add.png" Activated="ToolbarItem_Activated"/>
</ContentPage.ToolbarItems>
</ContentPage>
and here is my C# Code:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace ODC_Foto_ConWin_v1
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class YardList : ContentPage
{
public YardList()
{
InitializeComponent();
GetJSON();
}
private void yardListSyncButton_Clicked(object sender, EventArgs e)
{
GetJSON();
}
private void ToolbarItem_Activated(object sender, EventArgs e)
{
// code for manual process
}
public async void GetJSON()
{
var client = new System.Net.Http.HttpClient();
var response = await client.GetAsync("http://x.x.x.x/xample.JSON");
string json = await response.Content.ReadAsStringAsync();
RootObject rootObject = new RootObject();
ListView listViewJson = new ListView();
if (json != "")
{
rootObject = JsonConvert.DeserializeObject<RootObject>(json);
}
listViewJson.ItemsSource = rootObject.process;
ProgressLoader.IsVisible = false;
}
public class Process
{
public string id { get; set; }
public string fzg_nr { get; set; }
public string fzg_kz { get; set; }
public string timestamp { get; set; }
}
public class RootObject
{
public string file_timestamp { get; set; }
public List<Process> process { get; set; }
}
}
}
Is this something about wrong DataBinding? Am I initiating the ItemSource at the wrong point?! Because when I set the datatemplate in the GetJSON() method the data is visible...
So far i tried a few examples but at some point there must be a little mistake. I am new programming (I'm normally a systemadministrator) so I don't where to start looking for the mistakes.
Any help is really appreciated.
Thanks in advance,
Paul
Short answer: don't create new list, use existing one - just remove ListView listViewJson = new ListView(); from GetJSON and it should work.
Long answer
In your XAML you have:
<ListView x:Name="listViewJson">
and in your GetJSON method you are creating NEW ListView and setting ItemSource like this:
public async void GetJSON()
{
ListView listViewJson = new ListView();
(...)
listViewJson.ItemsSource = rootObject.process;
}
So you have 2 ListViews, one in XAML, and one in GetJSON method. Your ListView in XAML has the same name like ListView in GetJSON method (listViewJson). Because ListView created in method is 'closer' in line listViewJson.ItemsSource = rootObject.process then ListView created in XAML,you are setting ItemSource of newly created ListView that was not added to your ContentView.
EDIT:
I see couple other minor issues in your code, not related to the question but because you are learning, I thing it's worth to point them out:
Labels in your ListView template do not have Grid as direct parent so Grid.Column="0" does not have any effect
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Grid.Column="0">
In C# it is a common practice to use PascalCase naming style for properties. I think that you did this: public string timestamp { get; set; } because of json format. You can use JsonPropertyAttribute to set your mapping between C# and json like this:
[JsonProperty("timestamp")]
public string Timestamp { get; set; }
You are hiding ProgressLoader at the end of GetJSON but you are not showing it at the beginning, so it is visible only on your fist GetJSON call (so in constructor).
now your are using code behind and it is totally ok when you are starting with Xamarin. Later on I would suggest you go take a look at MVVM pattern.

How to pass data between the View and the ViewModel

I'm a newbie in the MVVM design patter I'm trying to create a simple app where a list of students is shown in the main window and I want the user to be able to add a new student to the list I have accomplished the binding of the observable collection where the students' data are but how can I create a new user by fetching the data from the textboxes and using them as a parameter in a command
Here is my View
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="2*"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="NameTextBlock"
Text="Name"
Style="{StaticResource TextBlockTextStyle}"/>
<TextBlock x:Name="SurnameTextBlock"
Grid.Row="1"
Text="Surname"
Style="{StaticResource TextBlockTextStyle}"/>
<TextBlock x:Name="AgeTextBlock"
Grid.Row="2"
Text="Age"
Style="{StaticResource TextBlockTextStyle}"/>
<TextBox x:Name="NameTextBox"
Grid.Column="1"
Style="{StaticResource TextBoxTextStyle}"/>
<TextBox x:Name="SurnameTextBox"
Grid.Row="1"
Grid.Column="1"
Style="{StaticResource TextBoxTextStyle}"/>
<TextBox x:Name="AgeTextBox"
Grid.Row="2"
Grid.Column="1"
Style="{StaticResource TextBoxTextStyle}"/>
<ListBox x:Name="StudentListBox"
Grid.ColumnSpan="2"
Grid.Row="4"
Style="{StaticResource ListBoxStyle}"
ItemsSource="{Binding StudentList}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Text="{Binding Name}"
Style="{StaticResource TextBlockTextStyle}"/>
<TextBlock Text="{Binding Surname}"
Grid.Column="1"
Style="{StaticResource TextBlockTextStyle}"/>
<TextBlock Text="{Binding Age}"
Grid.Column="2"
Style="{StaticResource TextBlockTextStyle}"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="AddButton"
Grid.Row="7"
Grid.ColumnSpan="2"
HorizontalAlignment="Center"
Content="Add"
Margin="7,7,7,7"
Command="{Binding AddStudentCommand}"/>
</Grid>
And here is my ViewModel
public class MainViewModel : ViewModelBase
{
ObservableCollection<Student> studentList;
public MainViewModel()
{
//populate some sample data
studentList = new ObservableCollection<Student>()
{
new Student(){Name="John", Surname="Smith", Age="28"},
new Student(){Name="Barbara", Surname="Anderson", Age="23"}
};
}
public ObservableCollection<Student> StudentList
{
get { return studentList; }
set { RaisePropertyChanged("studentList"); }
}
Student selectedPerson;
public Student SelectedPerson
{
get { return selectedPerson; }
set
{
selectedPerson = value;
RaisePropertyChanged("SelectedPerson");
}
}
private RelayCommand _addStudentCommand;
public ICommand AddStudentCommand
{
get
{
return _addStudentCommand
?? (_addStudentCommand = new RelayCommand(() =>
{
Student student = new Student();
// here should be the logic of defining the name, surname,
// age and id of the newly created student
studentList.Add(student);
}));
}
}
}
I am using MVVMLight in the current project and there are a lot of thing that I do not understand so please explain how I should pass the data of the textboxes and what exactly should happen in the command that it is being used.
Tell me to add more of the code if necessary.
What I would do is create some properties that the textboxes are bound to in the ViewModel.
Like this for all three (in your viewmodel)
private string _Name;
public string Name
{
get { return _Name; }
set
{
_Name = value;
RaisePropertyChanged("Name");
}
}
Then, in the XAML, bind the textbox's text to this:
<TextBox x:Name="NameTextBox"
Text="{Binding Name}"
Grid.Column="1"
/>
Finally in the AddStudent Command you reference the properties in the viewmodel that are bound to the textboxes.
private RelayCommand _addStudentCommand;
public ICommand AddStudentCommand
{
get
{
return _addStudentCommand
?? (_addStudentCommand = new RelayCommand(() =>
{
Student student = new Student();
student.Name = this.Name;
student.Surname = this.Surname;
student.Age = this.Age;
// here should be the logic of defining the name, surname,
// age and id of the newly created student
_StudentList.Add(student);
}));
}
}
(cheekily posted from my comment)
As you've stated, you've not had much experience and don't understand much with MVVM, so although I could answer this question, I think the best thing I could do is provide you with a few links to watch :
youtube.com/watch?v=BClf7GZR0DQ
and
channel9.msdn.com/blogs/kreekman/
The second video is from the guy who wrote MVVM-light.
They basically cover the same material, but both bring a slightly different perspective!

Categories

Resources