Data binding combobox with list from WCF Service - c#

I am developing an app(MVVM pattern) for windows store using WCF service to receive data from database.
I want to data bind a list of categories into combobox, but it's not working for me, I searched the web and still didn't find a solution.
Class Category:
public Category(Category c)
{
this.Id=c.Id;
this.Name = c.Name;
}
public int Id { get; set; }
public string Name { get; set; }
Xaml:
<ComboBox x:Name="ChooseCategory"
ItemsSource="{Binding ListCategories}"
DisplayMemberPath="Name"
SelectedValuePath="Id"
SelectedValue="{Binding SelectedItem, Mode=TwoWay}"/>
ViewModel:
public ObservableCollection<Category> ListCategories { get; private set; }
in the OnNavigatedTo function:
var listCategory = await proxy.GetAllCategoriesAsync();
List<Category> list = new List<Category>();
foreach (var item in listCategory)
{
list.Add(new Category(item));
}
ListCategories = new ObservableCollection<Category>(list);
Anyone???

You need to implement INotifyPropertyChanged in order to let UI know that you have changed the ListCategories collection.
In your ViewModel, implement interface INotifyPropertyChanged
public class YourViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
var handler = PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
private ObservableCollection<Category> _categories;
public ObservableCollection<Category> ListCategories
{
get { return _categories; }
set
{
if (_categories != value)
{
_categories = value;
OnPropertyChanged("ListCategories");
}
}
}

Related

How to set combo box value in WPF using MVVM architecture

I created a POC in WPF MVVM architecture.In which I used combo box control you can see in the code below.
<ComboBox Name="DeptCombo" Grid.Row="4" Grid.Column="1" ItemsSource="{Binding DepartmentList,Mode=TwoWay}" SelectedItem="{Binding Path=CurrentDepartment,Mode=TwoWay}" DisplayMemberPath="DepartmentName">
</ComboBox>
here CurrentDepartment is a property of Department class.
Everything is fine, I filled that combo , saved that combo value in the database, But the only problem I was facing is, I am not able to set the saved database value in that combo.I don't get any solution regarding that.Please help me.
Add UpdateSourceTrigger
SelectedItem="{Binding Path=CurrentDepartment,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}"
Еhe code should look something like this:
class ViewModel: INotifyPropertyChanged
{
public ObservableCollection<string> Datas { get; set; } = new ObservableCollection<string>()
{
"FF", "AA", "BB"
};
private string currentItem;
public string CurrentItem
{
get => currentItem;
set
{
currentItem = value;
OnPropertyChanged("CurrentItem");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string prop="")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
}
Example with Model:
PersonModel.cs:
class PersonModel
{
public string Name { get; set; }
public int Age { get; set; }
}
ViewModel.cs:
class ViewModel: INotifyPropertyChanged
{
public ObservableCollection<PersonModel> Datas { get; set; } = new ObservableCollection<PersonModel>()
{
new PersonModel(){Age = 10, Name="Tom"},
new PersonModel(){Age = 10, Name="Mark"},
};
private PersonModel currentItem;
public PersonModel CurrentItem
{
get => currentItem;
set
{
currentItem = value;
OnPropertyChanged("CurrentItem");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string prop="")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop));
}
}
MainWindow.xaml:
<ComboBox ItemsSource="{Binding Datas}" SelectedItem="{Binding CurrentItem, UpdateSourceTrigger=PropertyChanged}"
Height="100" Width="100">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Age}"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
Department Class :
public class Department : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertychanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private int id;
public int Id
{
get { return id; }
set { id = value; OnPropertychanged("Id"); }
}
private string departmentName;
public string DepartmentName
{
get { return departmentName; }
set { departmentName = value; OnPropertychanged("DepartmentName"); }
}
private bool isActive;
public bool IsActive
{
get { return isActive; }
set { isActive = value; OnPropertychanged("IsActive"); }
}
}
View Model :
private ObservableCollection<Department> departmentList;
public ObservableCollection<Department> DepartmentList
{
get { return departmentList; }
set { departmentList = value; OnPropertyChanged("DepartmentList"); }
}
private Department currentDepartment;
public Department CurrentDepartment
{
get { return currentDepartment; }
set { currentDepartment = value; OnPropertyChanged("CurrentDepartment"); }
}
private void DepartmentPop()
{
DepartmentList = new ObservableCollection<Department>
(objDepartmentService.GetAll());
}

Deleting and Editing an item in a listview with Viewmodel and without using the codebehind

In the shown code i need to know the coding to be replaced in place of question mark in the code. I need to delete,edit and update the item in the list view without writing any code in code behind. I only want to do these operations by bindin view with view model through Icommand
This a class in my model Playlist.cs
namespace MvvmDemo.Models
{
public class Playlist
{
public string Title { get; set; }
}
}
This is a class in my viewmodel PlaylistsViewModel.cs
namespace MvvmDemo.ViewModels
{
public class PlaylistsViewModel
{
public ObservableCollection Playlists { get; private set; } = new ObservableCollection();
public ICommand AddPlaylistCommand { get; private set; }
public ICommand DeletePlaylistCommand { get; private set; }
public ICommand EditPlaylistCommand { get; private set; }
public PlaylistsViewModel()
{
AddPlaylistCommand = new Command(AddPlaylist);
DeletePlaylistCommand = new Command(DeletePlaylist);
}
public void AddPlaylist()
{
var newPlaylist = "Playlist " + (Playlists.Count + 1);
Playlists.Add(new Playlist { Title = newPlaylist });
}
public void DeletePlaylist()
{
????????????????
}
public void EditPlaylist()
{
????????????????
}
}
}
you have to make the command is parameterised and pass binding data through the parameter.
and from that data you can get the index value of selected.using that remove the item from the list.
Playlists.RemoveAt("INDEX_NUMBER");
To update it in the view use "INotifyProperty" also
If you want to delete and edit item in ListView, firstly, you should need to use ICommand, then you could need to use INotifyPropertyChanged to implement Inotify.
I do one sample that you can take a look. Choosing one Item and long press with the left mouse button, you will see two ways, delete Item and Edit Item action.
<ContentPage.Content>
<StackLayout>
<ListView
x:Name="mylistview"
ItemsSource="{Binding lists}"
SelectedItem="{Binding selecteditem}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.ContextActions>
<MenuItem
Command="{Binding BindingContext.DeletePlaylistCommand, Source={x:Reference Name=mylistview}}"
IsDestructive="true"
Text="Delete Item" />
<MenuItem
Command="{Binding BindingContext.EditPlaylistCommand, Source={x:Reference Name=mylistview}}"
IsDestructive="true"
Text="Edit Item" />
</ViewCell.ContextActions>
<StackLayout Padding="15,0">
<Label Text="{Binding Title}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Page19 : ContentPage, INotifyPropertyChanged
{
public ObservableCollection<Playlist> lists { get; set; }
//public RelayCommand1 AddPlaylistCommand { get; set; }
public RelayCommand DeletePlaylistCommand { get; set; }
public RelayCommand EditPlaylistCommand { get; set; }
private Playlist _selecteditem;
public Playlist selecteditem
{
get { return _selecteditem; }
set
{
_selecteditem = value;
RaisePropertyChanged("selecteditem");
}
}
public Page19 ()
{
InitializeComponent ();
lists = new ObservableCollection<Playlist>()
{
new Playlist(){Id=1,Title="list 1"},
new Playlist(){Id=2, Title="list 2"},
new Playlist(){Id=3,Title="list 3"},
new Playlist(){Id=4,Title="list 4"},
new Playlist(){Id=5,Title="list 5"},
new Playlist(){Id=6,Title="list 6"},
};
DeletePlaylistCommand = new RelayCommand(DeletePlaylist);
EditPlaylistCommand = new RelayCommand(EditPlaylist);
selecteditem = lists[0];
this.BindingContext = this;
}
public void AddPlaylist()
{
}
public void DeletePlaylist()
{
Playlist item = selecteditem;
lists.Remove(item);
}
public void EditPlaylist()
{
Playlist item = selecteditem;
int id = item.Id;
foreach(Playlist playl in lists.Where(a=>a.Id==id))
{
playl.Title = "chenge title";
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public class Playlist: INotifyPropertyChanged
{
private int _Id;
public int Id
{
get { return _Id; }
set
{
_Id = value;
RaisePropertyChanged("Id");
}
}
private string _Title;
public string Title
{
get { return _Title;}
set
{
_Title = value;
RaisePropertyChanged("Title");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Here is the RelayCommd:
public class RelayCommand : ICommand
{
readonly Action _execute;
public RelayCommand(Action execute)
{
if (execute == null)
throw new ArgumentNullException("execute");
_execute = execute;
}
public event EventHandler CanExecuteChanged;
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_execute();
}
}
You can use observablecollection. It will reflect add,remove operation of item to the listview. And for editing item you have to raise property changed for all property you are editing.To simplify that property changed you can implement property changed event to your Playlist model class.
Like
public void DeletePlaylist()
{
Playlists.Remove(newPlaylist);
}
public void EditPlaylist()
{
newPlaylist.Title="Refreshed Playlist"
}
public class Playlist:INotifyPropertyChanged
{
private string title;
public string Title
{
get{return title;}
set{title=value;
NotifyPropertyChanged();}
}
}

Model and ViewModel Consept MVVM WPF

I want to read some data from database and do some process on them and then view them in the view.
I read a lot about MVVM and now I am confused.
Imaging I read a person entity from database with Name attribute.
please make a small code and show me how should I make my model and ViewModel.
I guess it we will be something like this :
public class PersonModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string Name;
public string name
{
get
{
return Name;
}
set
{
Name = value;
onpropertychanged("name");
}
}
public PersonModel( string s)
{
name = s;
}
public void onpropertychanged(string PName)
{
if (PropertyChanged !=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(PName));
}
}
}
public class PersonViewModel
{
public ObservableCollection <PersonModel> list { get; set; }
public PersonViewModel()
{
list = new ObservableCollection<model>();
list.Add(new model("abc"));
list.Add(new model("def"));
}
public void change()
{
list[1].name = "changed";
}
}
public class ViewModelBase
{
public PersonViewModel vperson { get; set; }
public ViewModelBase()
{
vperson = new PersonViewModel();
vperson.change();
}
}
Edite : Where should database connections be?
Edite :
<Grid>
<TextBox Text="{Binding vperson.list[1].name}" />
</Grid>
</Window>
I edited your classes and is working
public class PersonModel : INotifyPropertyChanged
{
private string _name;
public string Name
{
get => _name;
set
{
if (_name == value) return;
_name = value;
OnPropertyChanged();
}
}
public PersonModel(string name)
{
_name = name;
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class PersonViewModel
{
public ObservableCollection<PersonModel> Items { get; set; }
public PersonViewModel()
{
Items = new ObservableCollection<PersonModel> { new PersonModel("abc"), new PersonModel("def") };
}
public void Change()
{
Items[1].Name = "changed";
}
}
public class ViewModelBase
{
public PersonViewModel PersonViewModel { get; set; }
public ViewModelBase()
{
PersonViewModel = new PersonViewModel();
PersonViewModel.Change();
}
}
//Use the dataContext in this way, will help you with the strong type
xmlns:viewModels="clr-namespace:WpfApp1.ViewModels"
<Window.DataContext>
<viewModels:ViewModelBase />
</Window.DataContext>
<Grid>
<TextBox Text="{Binding PersonViewModel.Items[1].Name}" />
</Grid>

observable collection not changing combobox

I have an observable collection which is the item source to a combo box. When I add a new item to the observable collection, it appears in the combobox. However, when I update an existing item, it does not update the combo box. What am I doing wrong?
xaml:
<ComboBox ItemsSource="{Binding ChildGroupOC}" DisplayMemberPath="childGroupName" />
observable collection property:
public ObservableCollection<ChildGroupBO> ChildGroupOC
{
get
{ return childGroupOC;}
set
{
childGroupOC = value;
}
}
public class ChildGroupBO: INotifyPropertyChanged
{
public int parentGroupId { get; set; }
public int childGroupId { get; set; }
public string childGroupName { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
}
Your implementation of ChildGroupComboBoxBO not only has to implement INotifyPropertyChanged but also call the event on changes:
OnPropertyChanged("parentGroupId");
Example from MSDN:
public class Person : INotifyPropertyChanged
{
private string name;
// Declare the event
public event PropertyChangedEventHandler PropertyChanged;
public Person()
{
}
public Person(string value)
{
this.name = value;
}
public string PersonName
{
get { return name; }
set
{
name = value;
// Call OnPropertyChanged whenever the property is updated
OnPropertyChanged("PersonName");
}
}
// Create the OnPropertyChanged method to raise the event
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}
}

Listbox First Item Selected in mvvm

I am new to mvvm. I have a listbox in my silverlight application which is binded to a observable collection in view model i want to make the listbox with first item selected. I tired this but it doesnt work.
<ListBox Height="431" Canvas.Left="17" Canvas.Top="77" Width="215" FontSize="13" ItemsSource="{Binding Path=Categorys, Mode=TwoWay}" DataContext="{Binding}" SelectedItem="{Binding CurrentCategory, Mode=TwoWay}" ItemTemplate="{StaticResource CategoryDataTemplate}" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Name="lst_category">
then i added this in mainpage load of mainpage viewmodel
CurrentCategory = Categorys[0];
Can any one Help me
Do the following steps:
Make sure that the collection Categorys is filled already. You might need to use AsycCTP, Asynchronous Programming with Async and Await or some other mechanism to first wait for the collection to be filled.
The await operator is applied to a task in an asynchronous method to suspend the execution of the method until the awaited task completes. The task represents ongoing work.
Implement INotifyPropertyChanged in ViewModel exposing the Property, CurrentCategory and raise the event of PropertyChanged from within the Setter of the Property.
private Category _currentCategory = null;
public Category CurrentCategory
{
get { return _currentCategory; }
set
{
if (_currentCategory != value)
{
_currentCategory = value;
// Update bindings
RaisePropertyChanged("CurrentCategory");
}
}
}
Now you can use the same piece of code:
CurrentCategory = Categorys[0];
Try using ICollectionView and IsSynchronizedWithCurrentItem. The CollectionView has all the functionality you need. For example MoveToFirst().
Xaml:
<ListBox ItemsSource="{Binding Categories}"
DisplayMemberPath="Name"
IsSynchronizedWithCurrentItem="True" />
ViewModel:
public class ViewModel :INotifyPropertyChanged
{
private ObservableCollection<Category> _categories = new ObservableCollection<Category>();
private Category _currentCategory;
public ObservableCollection<Category> Categories
{
get { return _categories; }
set { _categories = value; OnPropertyChanged("Categories");}
}
public Category CurrentCategory
{
get { return _currentCategory; }
set { _currentCategory = value; OnPropertyChanged("CurrentCategory");}
}
public ICollectionView CategoriesView { get; private set; }
public ViewModel()
{
Categories.Add(new Category{Id = Guid.NewGuid(), Name = "Cat1"});
Categories.Add(new Category{Id = Guid.NewGuid(), Name = "Cat2"});
Categories.Add(new Category{Id = Guid.NewGuid(), Name = "Cat3"});
CategoriesView = CollectionViewSource.GetDefaultView(Categories);
CategoriesView.CurrentChanged += OnCategoriesChanged;
CategoriesView.MoveCurrentToFirst();
}
private void OnCategoriesChanged(object sender, EventArgs e)
{
var selectedCategory = CategoriesView.CurrentItem as Category;
if (selectedCategory == null) return;
CurrentCategory = selectedCategory;
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
public class Category
{
public Guid Id { get; set; }
public string Name { get; set; }
}
You Should Try This Way also.................
List c = new List
CurrentCategory = c.firstOrDefault()

Categories

Resources