I have to bind the changes of checkbox in the listview.
checkbox should work in such a way that if i select all checkbox and uncheck a single checkbox then header checkbox should deselect. Same way if i have 3 child checkbox ,and individually select all then parent checkbox should select.
i am using MVVM pattern
xaml
<GridViewColumn Width="80" >
<GridViewColumn.Header >
<!--<CheckBox x:Name="cbSelectAll" IsChecked="{Binding ModelDetails.IsChecked}" Command="{Binding cbSelectAll_Checked}"/>-->
<CheckBox x:Name="cbSelectAll" Command="{Binding CbSelectAll_Checked}" IsChecked="{Binding IsChecked, UpdateSourceTrigger=PropertyChanged}" />
</GridViewColumn.Header>
<GridViewColumn.CellTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<WrapPanel x:Name="Layout" >
<CheckBox IsChecked="{Binding IsSelected,Mode=TwoWay}" Command="{Binding CheckSingle}"/>
</WrapPanel>
</StackPanel>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
viewmodel.cs
public class Item : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
//publishing the event in current classs
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public Item(string name, string matches, string date, bool isSelected)
{
Name = name;
Type = matches;
Date = date;
IsSelected = isSelected;
}
private bool _isSelected;
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
OnPropertyChanged("IsSelected");
}
}
public string Name { get; set; }
public string Type { get; set; }
public string Date { get; set; }
}
here is the another class
public class AddedFilesViewModel : INotifyPropertyChanged
{
public ICommand CbSelectAll_Checked { get; set; }
public ICommand UploadBtnClick { get; set; }
public ICommand CheckSingle { get; set; }
CbSelectAll_Checked = new RelayCommands(SelectAllBtnExecute, SelectAllBtnCanExecute);
UploadBtnClick = new RelayCommands(UploadBtnExecute, UploadBtnCanExecuteUpload);
CheckSingle = new RelayCommands(SingleCheckBoxExecute, SingleCheckBoxExecuteCanExecute);
public void SelectAllBtnExecute(object param)
{
if (selectedStatus == false)
{
foreach (var item in Items)
{
item.IsSelected = true;
}
selectedStatus = true;
}
else
{
foreach (var item in Items)
{
item.IsSelected = false;
}
selectedStatus = false;
}
}
public void SingleCheckBoxExecute(object param)
{
MessageBox.Show("hello");
}
private bool _isChecked;
public bool IsChecked
{
get { return _isChecked; }
set
{
_isChecked = value;
OnPropertyChanged("IsChecked");
}
}
public bool SelectAllBtnCanExecute(object param)
{
return true;
}
public void UploadBtnExecute(object param)
{
List<Item> selectedFiles = new List<Item>();
if (Items != null)
{
foreach (var selectedItems in Items)
{
if (selectedItems.IsSelected)
{
selectedFiles.Add(selectedItems);
}
}
I can see the following block need to be changed, Please share full xaml file so I can understand your data binding.
<CheckBox IsChecked="{Binding IsSelected,Mode=TwoWay}" Command="{Binding CheckSingle}"/>
You need to edit it as "DataContext.IsSelected" and need to set binding source, it may be data grid or even full xaml based on your business logic to bind data. An example:
<CheckBox IsChecked="{Binding DataContext.IsSelected,Mode=TwoWay, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Command="{Binding CheckSingle}"/>
I've just given sample example, there are many other ways to achive it.
Maybe I am saying shit but I would try that:
Remove all commands
in isChecked set I would put all you put in selectAllButtonExecute
in isChecked get I would check if all checkbox are checked and return true or false accordingly
in IsSelected set I would add OnPropertyChanged("IsChecked");
Related
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());
}
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();}
}
}
I've read through probably 20 different posts and still can put together what I'm looking to do (maybe I'm going about it the wrong way?).
I want to make a window with a few checkboxes. These checkboxes need to have their IsChecked value bound to a member variable of an object in a List.
I'm trying something like this:
XAML
<CheckBox IsChecked="{Binding Features[0].Selected, Mode=TwoWay}">
<TextBlock Text="Feature 1" />
</CheckBox>
<CheckBox IsChecked="{Binding Features[1].Selected, Mode=TwoWay}">
<TextBlock Text="Feature 2" />
</CheckBox>
ViewModel
public static enum MyFeatureEnum
{
FEATURE1,
FEATURE2,
FEATURE3,
...
}
public class Feature : INotifyPropertyChanged
{
private bool _supported;
private bool _visible;
private bool _selected;
public MyFeatureEnum FeatureEnum { get; set; }
public bool Supported
{
get { return _supported; }
set { _supported = value; NotifyPropertyChanged("Supported"); }
}
public bool Visible
{
get { return _visible; }
set { _visible = value; NotifyPropertyChanged("Visible"); }
}
public bool Selected
{
get { return _selected; }
set { _selected = value; NotifyPropertyChanged("Selected"); }
}
public Feature(MyFeatureEnum featureEnum)
{
_supported = false;
_visible = false;
_selected = false;
FeatureEnum = featureEnum;
}
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
public List<Feature> Features { get; set; }
public InstallViewModel()
{
...
// Generate the list of features
Features = new List<Feature>();
foreach (MyFeatureEnum f in Enum.GetValues(typeof(MyFeatureEnum)))
{
Features.Add(new Feature(f));
}
...
}
This works.
What I want is to replace:
<CheckBox IsChecked="{Binding Features[0].Selected, Mode=TwoWay}">
with something like:
<CheckBox IsChecked="{Binding Features[InstallViewModel.MyFeatureEnum.FEATURE1].Selected, Mode=TwoWay}">
Is this possible?
Is this possible?
Not using a List<Feature> but you could use a Dictionary<MyFeatureEnum, Feature>:
public class InstallViewModel
{
public Dictionary<MyFeatureEnum, Feature> Features { get; set; }
public InstallViewModel()
{
// Generate the list of features
Features = new Dictionary<MyFeatureEnum, Feature>();
foreach (MyFeatureEnum f in Enum.GetValues(typeof(MyFeatureEnum)))
{
Features.Add(f, new Feature(f));
}
}
}
<CheckBox IsChecked="{Binding Features[FEATURE1].Selected, Mode=TwoWay}" />
One of my classes
public class CheckedListItem<T> : INotifyPropertyChanged
has the method
public bool IsChecked
{
get { return isChecked; }
set
{
isChecked = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
}
}
}
My XAML looks like
<ListBox ItemsSource="{Binding Employee}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked}" Content="{Binding Path=Item.Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
My employee.cs file
public class Employee
{
public string Name { get; set; }
}
I cant figure out how I can write back to the database when a item is checked or unchecked.
I would appreciate any help and would be more than happy to post the entire code for any files you need to see.
You should be able to get what you want by adding TwoWay for mode and PropertyChanged on UpdateSourceTrigger.
Final XAML will then be:
<ListBox ItemsSource="{Binding Employee}" >
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding IsChecked, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" Content="{Binding Path=Item.Name}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
EDIT:
By the way, I think you might be setting your ItemsSource incorrectly. I'm sure what you want is to bind that listbox to a collection of Employees?
Something like:
public ObservableCollection<Employee> Employees
{
get { return _employees; }
set
{
_employees = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Employees"));
}
}
}
I misunderstood the question so here comes second edit:
Your class files would instead look like this:
public partial class MainWindow : INotifyPropertyChanged
{
private ObservableCollection<MutableKeyValuePair<Employee, bool>> _employees;
public MainWindow()
{
InitializeComponent();
Employees = new ObservableCollection<MutableKeyValuePair<Employee, bool>>
{
new MutableKeyValuePair<Employee, bool>(new Employee("Joakim"), false),
new MutableKeyValuePair<Employee, bool>(new Employee("SoftwareIsFun"), false),
};
}
public ObservableCollection<MutableKeyValuePair<Employee, bool>> Employees
{
get { return _employees; }
set
{
_employees = value;
OnPropertyChanged(nameof(Employees));
}
}
public void UpdateDatabase()
{
foreach (var employee in Employees)
{
if (employee.Value)
{
//DATABASE LOGIC HERE
}
}
}
}
public class MutableKeyValuePair<TKey, TValue>
{
public TKey Key { get; set; }
public TValue Value { get; set; }
public MutableKeyValuePair()
{
}
public MutableKeyValuePair(TKey key, TValue value)
{
Key = key;
Value = value;
}
}
public class Employee
{
public Employee(string name)
{
Name = name;
}
public string Name { get; set; }
}
XAML:
<DataGrid ItemsSource="{Binding Employees}" AutoGenerateColumns="False">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Key.Name}"/>
<DataGridCheckBoxColumn Binding="{Binding Value}"/>
</DataGrid.Columns>
</DataGrid>
i made check box in wpf ,Got it from Internet.I want to see which item is checked or unchecked.Any idea how to do this
here goes the code
Class
public class CheckedListItem
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsChecked { get; set; }
public string Email { get; set; }
}
Usage
List<CheckedListItem> AvailablePresentationObjects = new List<CheckedListItem>();
CheckedListItem item = new CheckedListItem();
for (int i = 0; i < 10; i++)
{
item = new CheckedListItem();
item.Id = i;
item.Name = i.ToString();
item.IsChecked = false;
AvailablePresentationObjects.Add(item);
}
list.ItemsSource = AvailablePresentationObjects;
XMAL
<ListBox x:Name="list" Margin="3,277,0,0" Height="234" VerticalAlignment="Top" Selec
tionMode="Extended">
<ListBox.ItemTemplate>
<HierarchicalDataTemplate>
<my:RibbonCheckBox Label="{Binding Name}" IsChecked="{Binding IsChecked}" />
</HierarchicalDataTemplate>
</ListBox.ItemTemplate>
</ListBox>
took it from Here
Checked ListBox
Question is
How to implement property change so
that i can know which item was checked
and which was unchecked
My Code solution
You can get collection of selected items: list.SelectedItems.
Each item you can cast to CheckedListItem and check that item is checked.
If you want to handle property changing, you should implement interface INotifyPropertyChanged in CheckedListItem class
Example of INotifyPropertyChanged:
Add this to your class and call OnPropertyChanged in properties:
private boolean _isChecked;
public boolean IsChecked
{
get { return _isChecked; }
set
{
_isChecked= value;
OnPropertyChanged("IsChecked");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(name));
}
}