I'm following MVVM pattern. I have a listview control which has multiple checkboxes. my viewmodel has collection of Student which is bounded to listview control.
public ObservableCollection<Student> students{ get; private set; }
private ObservableCollection<Student> _displays { get; set; }
viewmodel doesn't know anything about the view so it doesn't access to the listview control
I tried by defining the Student class by below
public class Student
{
public string Name{ get; set; }
public string class { get; set; }
}
In viewmodel, i want to perform some action when user select/unselect the checkbox.
how can I get which items are checked or not, how can i get selected item state in viewmodel?
I'm following mvvm pattern.
In WPF, we generally use data binding. This means that ideally, you would have data bound a property of your Student class to a Checkbox in the UI:
public class Student : INotifyPropertyChanged
{
public bool IsSomething { get; set; } // Implement INotifyPropertyChanged here
...
}
...
<Checkbox IsChecked="{Binding IsSomething}" />
If you do this, then you can find out which Checkboxes were checked simply by looking at the relevant Student object from your view model:
bool isSomething = CurrentStudent.IsSomething;
If you want to react to the changing value, then you just have to monitor the property for changes:
public bool IsSomething
{
get { return isSomething; }
set
{
if (value != isSomething)
{
isSomething= value;
NotifyPropertyChanged("IsSomething");
if (isSomething) CheckedBoxWasChecked();
else CheckedBoxWasUnChecked();
}
}
}
Can you check multiple items at a time?
If not, you can simple add a SelectedItem property to your view model and bind the SelectedItem property of the listView to the SelectedItem property of the view model.
If you need to be able to check more than one item at a time, you can add a boolean IsSelected property to the Student class. Then in your data template for the list view, bind the IsChecked property of the checkbox to the IsSelected property of the Student.
Please make sure your view model and student class implement INotifyPropertyChanged, etc.
Related
I have the following visual tree
MainWindow
|--------UserControl
|----------ChildListView1
|--------ChildListView2
When user selects an item in ChildListView1, The ViewModel object of that item will be taken and it has a property called ConfigParams which has to be bound to ChildListView2.
Here is my view model
public class Equipment
{
public string Name {get; set;} //TODO: Change to Raise PropertyChanged on set
public ObservableCollection<ConfigParams> {get;set;}
}
Here is MainWindow's view model
public class MainViewModel
{
public ObservableCollection<Equipment> Equipments {get;set;}
}
In the xaml.cs of my UserControl I added the following property
public ListView ListInstances { get { return ChildListView1; } }
Added the following ItemsSource binding to my ChildListView2
ItemsSource="{Binding ListInstances.SelectedItem.ConfigParams, ElementName=MyUserControlName}"
I use MVVM pattern in my WPF application.
I have ObservableCollection Records in my ViewModel.
public enum RecordState
{
NotChanged,
Changed,
Added,
Deleted,
AlreadyExist
}
public class Record
{
public string FirstId { get; set; }
public RecordState State { get; set; }
public string CurrentId
{
get { return GetIdFromInstance(Instance); }
}
public MyStronglyTypedClass Instance { get; set; }
}
public class MyViewModel
{
public ObservableCollection<Record> Records;
// other code
}
In View i have DataGrid.
<DataGrid ItemsSource="{Binding }" //>
What i have to write(if that possible) in ItemsSource="{Binding /* here */}", so that Datagrid Items changed to
Records[0].Instance
Records[1].Instance
Records[2].Instance
...
Records[Records.Count-1].Instance
{Binding} means that your ItemsSource is the DataContext of that DataGrid(probably inherited from ancestor elements).
What you should do is set the DataContext of your top-level element(Window, UserControl etc..) to your ViewModel class.
And then as Gary suggested:
<DataGrid ItemsSource="{Binding Records}">
The link you gave about dynamic elements does the same in that matter, it adds more complicated element bindings and DataTemplates.
Description:
First I created an ObservableCollection which is accessed via the public property MyCollection. Now if I bind my DataGrid UI to MyCollection it will recognize collection changes, but not if MyCollection itself changes (ie. UpdateCollection method). To solve this issue I applied the familiar 'PropertyChanged("MyCollection")' to the MyCollection Property.
Now I found the need to group my DataGrid Content which requires a Collection View layer. When I added and binded to the CollectionView the UI no longer updates when MyCollection gets re-assigned. I read that only CollectionChanged propagate from the Source to the View. I guess in my case it is the PropertyChange on MyCollection that needs to somehow trigger a CollectionChanged event on the Source or View.
Question:
How can I get a re-assigmend on MyCollection to trigger a UI update, which is bound to a View of MyCollection?
Note: The reason for re-assigning MyCollection is due to a Modular MEF/MVVM architecture.
public class MyViewModel
{
public MyViewModel()
{
MyCollectionViewSource = new CollectionViewSource() { Source = MyCollection};
// The DataGrid is bound to this ICollectionView
MyCollectionView = MyCollectionViewSource.View;
}
// Collection Property
// NotifyPropertyChanged added specifically to notify of MyCollection re-assignment
ObservableCollection<MyObject> _MyCollection;
public ObservableCollection<MyObject> MyCollection
{
get {return _MyCollection;}
set {if (value != _MyCollection)
{_MyCollection = value;
NotifyPropertyChanged("MyCollection");}}
}
public MyCollectionViewSource PropertiesCollectionViewSource { get; private set; }
public ICollectionView = MyCollectionView { get; private set; }
// Method updates MyCollection itself (Called via ICommand from another ViewModel)
public void UpdateCollection(ObservableCollection<MyObject> NewCollection)
{
MyCollection = NewCollection;
}
}
Thanks,
Have a look at the Active Grouping Collection, its aimed at a different problem but might solve yours.
Building a smarter WPF CollectionView
Active Collection View on CodePlex
I am using the MVVM pattern in my project;
In my project I have a CheckedComboBoxEdit then bind to a Person List;
Public Class Person
{
Public Int Id { get; set; }
Public string Name { get; set; }
}
When User select some Items in CheckedComboBoxEdit, how can I get CheckedComboBoxEdit SelectedItems in my ViewModel?
You need a property on your ViewModel that binds to the CheckedComboBoxEdit SelectedItems property. You should probably look at related DevExpress posts.
<CheckedComboBoxEdit x:Name="cbPeople" SelectedItems="{Binding SelectedPeople}" ... />
I try to adopt entity-level validation (attributes validation on properties on entities) by create ViewModel that expose that Entity.
public class MyViewModel
{
public MyEntity MyEntity { get; set; }
}
I set binding in xaml to, this xaml page set its DataContext to instance of MyViewModel
TextBlock Text="{Binding MyEntity.MyProperty}"
When I load MyEntity from database and set it to MyViewModel, nothing happen. I also call NotifyPropertyChanged("MyEntity"); and it still nothing happen.
I try again by create MyProperty in MyViewModel
public class MyViewModel
{
private MyEntity MyEntity { get; set; }
public string MyProperty
{
get { return this.MyEntity.MyProperty; }
set { this.MyEntity.MyProperty = value; }
}
}
And changed xaml to bind to MyProperty. This time when I call NotifyPropertyChanged("MyProperty "); View get update correctly, when I input incorrect data, it has ValidationErrors at MyEntity but View don't raise that error (not show red border)
I want to know how can I get entity-level validation working with MVVM.
Hi
you must change the definition of ViewModel such as
public class MyViewModel:IDataErrorInfo
{
}
and implement interface.
this force View to show red border on error.
wish to help.