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));
}
}
Related
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");
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 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()
I have made a CheckedListBox using the following:
<ListBox x:Name="lst_checkBoxList" ItemsSource="{Binding}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox Content="{Binding Name}" IsChecked="{Binding IsChecked}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and am populating it using the following:
public List<CheckedListItem> listItems = new List<CheckedListItem>();
public class CheckedListItem
{
public int Id { get; set; }
public string Name { get; set; }
public bool IsChecked { get; set; }
public CheckedListItem(int id, string name, bool ischecked)
{
Id = id;
Name = name;
IsChecked = ischecked;
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
listItems.Add(new CheckedListItem(0, "item 1", false));
listItems.Add(new CheckedListItem(0, "item 2", false));
listItems.Add(new CheckedListItem(0, "item 3", false));
listItems.Add(new CheckedListItem(0, "item 4", false));
lst_checkBoxList.ItemsSource = listItems;
listItems[0].IsChecked = true; //This correctly sets the first CheckBox as checked.
}
private void button2_Click(object sender, RoutedEventArgs e)
{
listItems[0].IsChecked = true; //This does not affect the CheckBox, despite changing the value it is bound to.
}
If I change the data behind one of the CheckBoxes immediately after setting the ItemsSource, the CheckBox is ticked accordingly, but if I try to change the value anywhere else in the code the CheckBox remains unchecked...can anyone help me work out why?
You need to notify the control that the property it is bound to has been updated, by implementing the INotifyPropertyChanged interface in CheckedListItem:
public class CheckedListItem : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private bool _IsChecked;
public bool IsChecked
{
get { return _IsChecked; }
set
{
_IsChecked = value;
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs("IsChecked"));
}
}
}
You need to implement the INotifyPropertyChanged interface on your CheckedListItem class and then notify on any property changes.