How do you set the BindingContext of a nested collection in Maui? - xaml

I am not sure how to refer to another collection object for a BindingContext of a CollectionView inside another CollectionView in Maui/XAML. Take the following example:
XAML:
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="NestedContextExample.MainPage"
xmlns:model="clr-namespace:NestedContextExample"
Title="{Binding Name}">
<ContentPage.BindingContext>
<model:Form />
</ContentPage.BindingContext>
<ScrollView Padding="10">
<CollectionView ItemsSource="{Binding FieldGroups}">
<CollectionView.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding Name}" />
<!-- something like this -->
<CollectionView ItemsSource="{Binding Source={x:Reference Answers.Where(a => Fields.Contains(a.Field)}}">
<CollectionView.ItemTemplate>
<DataTemplate>
<VerticalStackLayout>
<Label Text="{Binding Field.Name}" />
<Label Text="{Binding Value}" />
</VerticalStackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</StackLayout>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</ScrollView>
Code Behind:
namespace NestedContextExample;
public partial class MainPage : ContentPage
{
public Form Form { get; set; }
public List<Answer> Answers { get; set; }
public MainPage()
{
InitializeComponent();
Form = new Form
{
Name = "My Form",
FieldGroups = new List<FieldGroup>
{
new FieldGroup
{
Name = "Group A",
Fields = new List<Field> {
new Field
{
Name = "Field 1"
},
new Field
{
Name = "Field 2"
}
}
},
new FieldGroup
{
Name = "Group B",
Fields = new List<Field> {
new Field
{
Name = "Field 3"
},
new Field
{
Name = "Field 4"
}
}
}
}
};
Answers = Form.FieldGroups.SelectMany(g => g.Fields).Select(f => new Answer
{
Field = f
}).ToList();
BindingContext = Form;
}
}
public class Form
{
public string Name { get; set; }
public List<FieldGroup> FieldGroups { get; set; }
}
public class FieldGroup
{
public string Name { get; set; }
public List<Field> Fields { get; set; }
}
public class Field
{
public string Name { get; set; }
}
public class Answer
{
public Field Field { get; set; }
public string Value { get; set; }
}
So, I want the nested collection to be bound to the subset of the list of Answer objects with fields within the current FieldGroup, rather than the Fields of the current FieldGroup. Note the ItemsSource="{Binding Source={x:Reference Answers.Where(a => Fields.Contains(a.Field)}}" - that obviously doesn't work, but that is what I am basically trying to achieve. How would I go about that?

Related

Xamarin Bindable Property The property 'FadePropertyOf' was not found in type 'FadableImageControl'

I'm working with Bindable Properties
I'm getting this error from my xaml file
The property 'FadePropertyOf' was not found in type 'FadableImageControl'.
it looks like a cast problem, but I haven't figure out a way to make my object to read this property ImageFadeProperty , ImageSourceOf works fine. Do any one have an idea of what I'm missing?
public partial class FadableImageControl : ContentView
{
public static readonly BindableProperty ImageSourceProperty =
BindableProperty.Create("ImageSourceOf",
typeof(ImageSource), typeof(FadableImageControl));
public ImageSource ImageSourceOf
{
get { return GetValue(ImageSourceProperty) as ImageSource; }
set { SetValue(ImageSourceProperty, value); }
}
public bool FadePropertyOf
{
get => (bool)GetValue(FadePropertyOfProperty);
set => SetValue(FadePropertyOfProperty, value);
}
public static readonly BindableProperty FadePropertyOfProperty =
BindableProperty.Create(
"FadePropertyOf",
typeof(bool),
typeof(FadableImageControl),
defaultValue: false,
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: async(BindableObject bindable, object oldValue, object newValue)=>
{
var myControl = bindable as FadableImageControl;
var o = oldValue;
var n = newValue;
var opacityControl = myControl.fadableImage;
if (opacityControl.Opacity == 0)
{
await opacityControl.FadeTo(1, 100);
}
else
{
await opacityControl.FadeTo(0, 100);
}
});
public FadableImageControl()
{
InitializeComponent();
}
}
Also added this in XAML:
<?xml version="1.0" encoding="UTF-8" ?>
<ContentPage
x:Class="animations.Views.MyPageInitComp"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:bindables="clr-namespace:animations.Views.Bindables">
<ContentPage.Content>
<StackLayout Padding="20" BackgroundColor="Pink">
<StackLayout Padding="20" BackgroundColor="DeepPink">
<bindables:FadableImageControl FadePropertyOfProperty="" ImageSourceOf="ino.png" Opacity="0" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
This code works for me (I'm assuming the FadableImageControl is a ContentView):
<?xml version="1.0" encoding="UTF-8" ?>
<ContentView
x:Class="App3.Controls.FadableImageControl"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Name="thisControl">
<ContentView.Content>
<StackLayout BindingContext="{x:Reference thisControl}">
<Image Source="{Binding ImageSourceOf}" />
<Label Text="{Binding FadePropertyOf, StringFormat='FadePropertyOf: {0}'}" />
</StackLayout>
</ContentView.Content>
</ContentView>
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace App3.Controls
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class FadableImageControl : ContentView
{
public static readonly BindableProperty ImageSourceOfProperty =
BindableProperty.Create(
nameof(ImageSourceOf),
typeof(ImageSource),
typeof(FadableImageControl));
public ImageSource ImageSourceOf
{
get => GetValue(ImageSourceOfProperty) as ImageSource;
set => SetValue(ImageSourceOfProperty, value);
}
public static readonly BindableProperty FadePropertyOfProperty =
BindableProperty.Create(
nameof(FadePropertyOf),
typeof(bool),
typeof(FadableImageControl),
defaultValue: false,
defaultBindingMode: BindingMode.TwoWay,
propertyChanged: async (BindableObject bindable, object oldValue, object newValue) =>
{
var myControl = bindable as FadableImageControl;
var o = oldValue;
var n = newValue;
//pretend to fade image here
await Task.Delay(1);
}
);
public bool FadePropertyOf
{
get => (bool)GetValue(FadePropertyOfProperty);
set => SetValue(FadePropertyOfProperty, value);
}
public FadableImageControl()
{
InitializeComponent();
}
}
}

MVC checkbox list bounding to model

I am trying to collect all the options that the user have selected for a checkbox list. The checkbox list is built using a foreach loop and I have a int[] that I am trying to put the id into. Any help would be great.
View
#{
int idxFormats = 0;
foreach (var item in Model.ListOfFormats)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="chkFormat" />
<label asp-for=#item.Selected>#Html.Raw(#item.Name)</label>
#Html.HiddenFor(m => Model.selectedFormats[idxFormats]);
</div>
idxFormats++;
}
#Html.ValidationMessageFor(model => model.selectedFormats[idxFormats])
}
Model
public List<GenericValues> ListOfFormats { get; set; }
[Display(Name = "At least one 'Format' must be selected")]
public int[] selectedFormats { get; set; }
Change the Checkbox name to selectedFormats
<input type="checkbox" value=#item.Value name="selectedFormats" />
Test example:
Model:
public class Test
{
public List<GenericValues> ListOfFormats { get; set; }
public int[] selectedFormats { get; set; }
}
public class GenericValues
{
public int Value { get; set; }
public string Name { get; set; }
public bool Selected { get; set; }
}
View:
#model Test
#{
ViewData["Title"] = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h1>Index</h1>
<form method="post">
#{
foreach (var item in Model.ListOfFormats)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="selectedFormats" />
<label asp-for=#item.Selected>#Html.Raw(#item.Name)</label>
</div>
}
}
<input type="submit" value="submit" />
</form>
Controller:
public IActionResult Index()
{
Test test = new Test
{
ListOfFormats = new List<GenericValues>
{
new GenericValues
{
Name = "A",
Value = 1,
},
new GenericValues
{
Name = "B",
Value = 2,
},
new GenericValues
{
Name = "C",
Value = 3,
}
}
};
return View(test);
}
[HttpPost]
public IActionResult Index(Test test)
{
return Ok();
}
Result:
if you are looking to put id as value of your idxFormats then use this code in your checkbox:
<input type="checkbox" value=#item.Value name="chkFormat" id="#idxFormats" />
Edit:
I am not so familiar with c#, I tested with minimum code :
// Replace the model correct path by yours
#model IEnumerable<WebApplication1.Models.MyModels.ListOfFormats>
#{
int idxFormats = 0;
foreach (var item in Model)
{
<div class='col-md-6'>
<input type="checkbox" value=#item.Value name="chkFormat" id="#idxFormats"/>
<label>#Html.Raw(#item.Name)</label>
</div>
idxFormats++;
}
}

How to delete an Item selected form ListView in Xamarin

I'm building a Xamarin CrossPlatform App!
App contains 2 pages : HomePage, DetailGetData
HomePage:
This page contains a ListView which is displaying list of data form webapi in cells and whenever I clicked each cell it goes to DetailGetDatapage which shows the detail of that data.
Problem:
Now the problem is that I wanted to delete that selected item from DetailGetData page. A DeleteButton is placed and when i press that button that details and selected item should be deleted from the ListView as well.
How it is possible ?
ScreenShot DetailGetData :https://i.stack.imgur.com/TXg4G.png
ScreenShot HomePage : https://i.stack.imgur.com/g1Hn1.png
Code:
DetailGetData Xaml:
<?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="Last_MSPL.Views.DetailGetData">
<StackLayout HorizontalOptions="Center" VerticalOptions="Center">
<Label Text="{Binding employee_name}" x:Name="empname" FontSize="Medium" FontAttributes="Bold" />
<Label Text="{Binding employee_age}" x:Name="age" FontSize="Medium" FontAttributes="Bold" />
<Label Text="{Binding employee_salary}" x:Name="salary" FontSize="Medium" FontAttributes="Bold" />
<Button x:Name="DeleteItem" Text="Delete" Clicked="DeleteItem_Clicked" />
</StackLayout>
</ContentPage>
HomePage Xaml:
<?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="Last_MSPL.HomePage">
<AbsoluteLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<ListView x:Name="Demolist" ItemSelected="OnItemSelected" BackgroundColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell Height="100">
<ViewCell.ContextActions>
<MenuItem x:Name="OnMore" Clicked="OnMore_Clicked" CommandParameter="{Binding .}"
Text="More" />
<MenuItem x:Name="OnDelete" Clicked="OnDelete_Clicked" CommandParameter="{Binding .}"
Text="Delete" IsDestructive="True" />
</ViewCell.ContextActions>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand" Padding="30,0">
<Label Text="{Binding employee_name}" FontAttributes="bold" FontSize="Small" TextColor="Black" x:Name="en"/>
<Label Text="{Binding employee_age}" FontSize="Micro" TextColor="Black" FontAttributes="Italic"/>
<Label Text="{Binding id}" IsVisible="False" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<ImageButton Source="fedit.png"
BackgroundColor="Transparent"
AbsoluteLayout.LayoutFlags="PositionProportional"
AbsoluteLayout.LayoutBounds=".95,.95,55,55"
Clicked="ImageButton_Clicked">
</ImageButton>
</AbsoluteLayout>
</ContentPage>
HomePage.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using Newtonsoft.Json;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Last_MSPL.MenuItems;
using Last_MSPL.Views;
using System.Collections;
namespace Last_MSPL
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class HomePage : ContentPage
{
public IEnumerable ObjOrderList { get; private set; }
public HomePage()
{
((NavigationPage)Application.Current.MainPage).BarBackgroundColor = Color.Black;
InitializeComponent();
Get();
}
public async void Get()
{
HttpClient client = new HttpClient();
try
{
var respone = await client.GetStringAsync("http://dummy.restapiexample.com/api/v1/employees");
List<GetData> ObjOrderList = JsonConvert.DeserializeObject<List<GetData>>(respone);
var totalCount = ObjOrderList.Count;
Demolist.ItemsSource = ObjOrderList.GetRange(0, 40);
}
catch (Exception ex)
{
throw;
}
}
public async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
HttpClient client = new HttpClient();
if (Demolist.SelectedItem != null)
{
var respone = await client.GetStringAsync("http://dummy.restapiexample.com/api/v1/employees");
List<GetData> ObjOrderList = JsonConvert.DeserializeObject<List<GetData>>(respone);
var abc = (GetData)e.SelectedItem;
GetData data = new GetData();
data = ObjOrderList.ToList().Where(x => x.id == abc.id).FirstOrDefault();
var detailPage = new DetailGetData(data);
detailPage.BindingContext = e.SelectedItem as GetData;
Demolist.SelectedItem = null;
await Navigation.PushModalAsync(detailPage);
}
}
DetailGetData.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Http;
using Newtonsoft.Json;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Last_MSPL.MenuItems;
namespace Last_MSPL.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DetailGetData : ContentPage
{
public DetailGetData(GetData _data)
{
InitializeComponent();
BindingList(_data);
}
public void BindingList(GetData data)
{
empname.Text = data.employee_name;
age.Text = data.employee_age;
salary.Text = data.employee_salary;
}
public async void DeleteItem_Clicked(object sender, EventArgs e)
{
await Navigation.PopModalAsync();
}
}
}
You can realize the function of deleting the item by adding a static datasouce class. And set the Demolist.ItemsSource = DataSource.collection;
When click delete button in DetailGetData page, modify the Demolist.ItemsSource by deleting the item.
So the code is like this:
DataSource.cs
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text;
namespace App10
{
public static class DataSource
{
public static ObservableCollection<GetData> collection;
static DataSource()
{
}
public static void persist(List<GetData> collection)
{
//do something here
}
public static void initializeData(List<GetData> listdata)
{
collection = new ObservableCollection<GetData>(listdata);
}
}
}
MainPage.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
{
List<GetData> dataList;
public MainPage()
{
//((NavigationPage)Application.Current.MainPage).BarBackgroundColor = Color.Black;
InitializeComponent();
Get();
//RefreshList();
}
public async void Get()
{
HttpClient client = new HttpClient();
try
{
var respone = await client.GetStringAsync("http://dummy.restapiexample.com/api/v1/employees");
List<GetData> ObjOrderList = JsonConvert.DeserializeObject<List<GetData>>(respone);
var totalCount = ObjOrderList.Count;
dataList = ObjOrderList.GetRange(0, 40);
DataSource.initializeData(dataList);
Demolist.ItemsSource = DataSource.collection;
}
catch (Exception ex)
{
throw;
}
}
public async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
HttpClient client = new HttpClient();
if (Demolist.SelectedItem != null)
{
var respone = await client.GetStringAsync("http://dummy.restapiexample.com/api/v1/employees");
List<GetData> ObjOrderList = JsonConvert.DeserializeObject<List<GetData>>(respone);
var abc = (GetData)e.SelectedItem;
GetData data = new GetData();
data = ObjOrderList.ToList().Where(x => x.id == abc.id).FirstOrDefault();
var detailPage = new DetailGetData(data);
detailPage.BindingContext = e.SelectedItem as GetData;
Demolist.SelectedItem = null;
await Navigation.PushModalAsync(detailPage);
}
}
}
DetailGetData.xaml.cs
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class DetailGetData : ContentPage
{
public GetData thisData;
public DetailGetData(GetData _data)
{
InitializeComponent();
BindingList(_data);
thisData = _data;
}
public void BindingList(GetData data)
{
empname.Text = data.employee_name;
age.Text = data.employee_age;
salary.Text = data.employee_salary;
}
public async void DeleteItem_Clicked(object sender, EventArgs e)
{
GetData toberemoveditem = (from item in DataSource.collection
where item.id == thisData.id
select item)
.FirstOrDefault<GetData>();
DataSource.collection.Remove(toberemoveditem);
await Navigation.PopModalAsync();
}
}
Initialize your List in some class and make it static and use it in your Home Page. And then in your Detail Page in Delete event just write this code to remove the item from the list.
var remove = list.Where(x => x.employee_name == empname.Text).Single();
list.Remove(remove);
Change the code according to your model class. I hope it helps.

Bind checkboxes in listview MVVM

I am trying to bind checkbox as below but when I click on it it doesn't even stay checked.Below is my model that maps to the db.I would like to get selected item using the checked checkboxes so I can eventually grab the cost fields.I have attempted to follow the code example from Programming Windows Store Apps with C#.
by Matt Baxter-Reynolds and Iris Classon.I have updated my code to match answer provided by #Arnaud.The checkbox doesn't stay checked but the visibility of the button changes on clicking on the radiobuttons.
Model ServiceItem
public class ServiceItem:ModelItem
{
// key field...
[AutoIncrement(), PrimaryKey(), JsonIgnore]
public int Id { get; set; }
// other fields...
[Unique, JsonProperty("id")]
public int NativeId { get; set; }
[JsonProperty("name")]
public string Name { get; set; }
public decimal Cost
{
get
{
return GetValue<decimal>();
}
set
{
SetValue(value);
}
}
[JsonIgnore] //prefer not to have it on db has no value
public bool IsSelected
{
get
{
return GetValue<bool>();
}
set
{
SetValue(value);
}
}
public ServiceItem()
{
}
}
Below is the Viewmodel
ServicesPage ViewModel
public class ServicesPageViewModel : ViewModel, IServicesPageViewModel
{
public ObservableCollection<ServiceItem> Items { get; private set; }
public ICommand ContinueCommand { get; private set; }
public ServicesPageViewModel()
{
}
public override void Initialize(IViewModelHost host)
{
base.Initialize(host);
// setup...
this.Items = new ObservableCollection<ServiceItem>();
this.ContinueCommand = new DelegateCommand((args) => GetSelected(args as CommandExecutionContext));
}
}
Below is the xaml
ServicePage.xaml
<ListView ItemsSource="{Binding Items}"
IsItemClickEnabled="true"
Margin="10,10,10,0" TabIndex="1">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<CheckBox Content="{Binding Name}"
BorderBrush="{ThemeResource AppBarBackgroundThemeBrush}"
IsChecked="{Binding IsSelected, Mode=TwoWay}"></CheckBox>
<Button Content="{Binding Cost, Mode=TwoWay}"
Visibility="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}" Grid.Column="1">
Viewmodel
public abstract class ViewModel : ModelItem, IViewModel
{
// somewhere to hold the host...
protected IViewModelHost Host { get; private set; }
//other code omitted
}
Viewmodel interface Iviewmodel
public interface IViewModel : INotifyPropertyChanged
{
void Initialize(IViewModelHost host);
//other code omitted
}
ModelItem
public abstract class ModelItem : INotifyPropertyChanged
{
private Dictionary<string, object> Values { get; set; }
protected ModelItem()
{
this.Values = new Dictionary<string, object>();
}
public event PropertyChangedEventHandler PropertyChanged;
protected T GetValue<T>([CallerMemberName] string name = null)
{
if (this.Values.ContainsKey(name))
return (T)this.Values[name];
else
return default(T);
}
protected void SetValue(object value, [CallerMemberName] string name = null)
{
// set...
this.Values[name] = value;
// notify...
this.OnPropertyChanged(new PropertyChangedEventArgs(name));
}
protected void OnPropertyChanged([CallerMemberName] string name = null)
{
this.OnPropertyChanged(new PropertyChangedEventArgs(name));
}
protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, e);
}
}
you need to implement INotifyPropertyChanged on your class ServiceItem otherwise you will never raise any event when the value is updated.
Here is the code of my view. I have added a converter to display the cost only when items are selected:
<Page
x:Class="App4.CheckBoxPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App4"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
>
<Page.Resources>
<local:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
</Page.Resources>
<ListView ItemsSource="{Binding Items}"
IsItemClickEnabled="true"
Margin="10,10,10,0" TabIndex="1">
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="3*"></ColumnDefinition>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<CheckBox Content="{Binding Name}"
BorderBrush="{ThemeResource AppBarBackgroundThemeBrush}"
IsChecked="{Binding IsSelected, Mode=TwoWay}"></CheckBox>
<Button Content="{Binding Cost, Mode=TwoWay}" Visibility="{Binding IsSelected, Converter={StaticResource BooleanToVisibilityConverter}}" Grid.Column="1"></Button>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Page>
And the classes, I have used. ServiceItem needs to extend ModelItem so as to notify the view of changes on properties Cost and IsSelected. Without it, the View will only get the initial values of Cost and IsSelected and all updates on these properties will be ignored by the View.
public sealed partial class CheckBoxPage : Page
{
public CheckBoxPage()
{
var items = new ObservableCollection<ServiceItem>()
{
new ServiceItem() {Name = "Item 1", Id = 1, NativeId = 1, Cost = 123 },
new ServiceItem() {Name = "Item 2", Id = 2, NativeId = 2, Cost = 456 },
new ServiceItem() {Name = "Item 3", Id = 3, NativeId = 3, Cost = 789 },
new ServiceItem() {Name = "Item 4", Id = 4, NativeId = 4, Cost = 1011 },
};
Items = items;
this.InitializeComponent();
}
public ObservableCollection<ServiceItem> Items
{
get;
set;
}
}
public class ServiceItem : ModelItem
{
public int Id { get; set; }
public int NativeId { get; set; }
public string Name { get; set; }
public decimal Cost {
get
{
return GetValue<decimal>();
}
set
{
SetValue(value);
}
}
public bool IsSelected
{
get
{
return GetValue<bool>();
}
set
{
SetValue(value);
}
}
}

How to capture multiple checkboxes and radio buttons posted data by viewmodel ASP.Net MVC

i am new in MVC. so this is my html looks like
<form id='your-form' action='#Url.Action("Action","Controller")' method='post'>
<b>Gender</b><br />
<input type='radio' name='gender' value='Male' /> Male <br />
<input type='radio' name='gender' value='Female' /> Female <br />
<hr />
<b>Hobbies</b><br />
<input type='checkbox' name='hobbies' value='Reading' /> Reading <br />
<input type='checkbox' name='hobbies' value='Sports' /> Sports <br />
<input type='checkbox' name='hobbies' value='Movies' /> Movies <br />
<input type='submit' value='Update Profile' />
</form>
this way i am capturing data
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Index(string gender, string[] hobbies)
{
// Example output
var output = String.Format("The user's gender is <b>{0}</b> and they enjoy <b>{1}</b>", gender, String.Join(",", hobbies));
return Content(output);
}
}
but i like to know how could i capture it by viewmodel concept. anyone can help me with sample code. thanks
View models
public class HobbyVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
public class PersonVM
{
....
public string Gender { get; set; } // would be better to use an enum
public List<HobbyVM> Hobbies { get; set; }
}
In the GET method, initialize an instance of the view model and pass it to the view
public ActionResult Create()
{
PersonVM model = new PersonVM()
{
Hobbies = new List<HobbyVM>()
{
new HobbyVM(){ ID = 1, Name = "Reading" },
new HobbyVM(){ ID = 2, Name = "Sports" },
....// etc these would actually be loaded from a repository
}
};
return View(model);
}
[HttpPost]
public ActionResult Create(PersonVM model)
{
// map you view model to a instance of your data model
// save and redirect
}
View
#model PersonVM
#Html.BeginForm())
{
....
<label>
#Html.RadioButtonFor(m => m.Gender, "Male", new { id = "" })
<span>Male</span>
</label>
<label>
#Html.RadioButtonFor(m => m.Gender, "Female", new { id = "" })
<span>Female</span>
</label>
for(int i = 0; i < Model.Hobbies.Count; i++)
{
#Html.HidenFor(m => m.Hobbies[i].ID)
#Html.CheckBoxFor(m => m.Hobbies[i].IsSelected)
#Html.LabelFor(m => m.Hobbies[i].IsSelected, Model.Hobbies[i].Name)
}
<input type="submit" />
}