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}" ... />
Related
I'm using the MVVM pattern with WPF and have run into a problem, which I can simplify to the following:
I have a CardType model.
public class CardType
{
public int Id { get; set; }
public string Name { get; set; }
}
And I have a viewmodel that consumes CardType.
public class ViewModel : INotifyPropertyChanged
{
private CardType selectedCardType;
public CardType SelectedCardType
{
get { return selectedCardType; }
set
{
selectedCardType = value;
OnPropertyChanged(nameof(SelectedCardType));
}
}
public IEnumerable<CardType> CardTypes { get; set; }
// ... and so on ...
}
My XAML has a ComboBox that bases its items on CardTypes and should preselect an item based on SelectedCardType.
<ComboBox ItemsSource="{Binding CardTypes}"
DisplayMemberPath="Name"
SelectedItem="{Binding SelectedCardType}"/>
For reasons outside of my control, the SelectedCardType object will be a reference-unequal copy of the item in CardTypes. Therefore WPF fails to match the SelectedItem to an item in ItemsSource, and when I run the app, the ComboBox initially appears with no item selected.
I tried overriding the Equals() and GetHashCode() methods on CardType, but WPF still fails to match the items.
Given my peculiar constraints, how can I get ComboBox to select the correct item?
You might not be overriding Equals and GetHashCode properly. This should work for you. (However, just overriding Equals will work in your case but it's considered to be good practice to override GetHashCode too when you override Equals for a class)
public class CardType
{
public int Id { get; set; }
public string Name { get; set; }
public override bool Equals(object obj)
{
CardType cardType = obj as CardType;
return cardType.Id == Id && cardType.Name == Name;
}
public override int GetHashCode()
{
return Id.GetHashCode() & Name.GetHashCode();
}
}
You can use SelectedValue and SelectedValuePath:
<ComboBox ItemsSource="{Binding CardTypes}"
DisplayMemberPath="Name"
SelectedValue="{Binding ProductId, Mode=TwoWay}"
SelectedValuePath="Id"/>
Where ProductId is a int property with NotifyPropertyChanged.
Read a great explanation here:
Difference between SelectedItem, SelectedValue and SelectedValuePath
A workaround that you could do is to bind your SelectedItem to a string (instead of cardType), then create an object of type CardType using this string?
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.
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.
I have two datagrids in a single view but the collections which are ItemsSource of these datagrids are in different View Models. So is it possible to bind these two datagrids with the collections in two different View Models?
Go for a view model combining both:
public class ViewModelA {
public ObservableCollection<CustomClass> Items { get; set; }
/* properties, etc. */
}
public class ViewModelB {
/* properties, etc. */
}
public class CombiningViewModel {
public ViewModelA A { get; set; }
public ViewModelB B { get; set; }
}
Binding can be done like
<DataGrid ItemsSource="{Binding A.Items}">
<!-- Sample, not complete -->
</DataGrid>
No, not directly. You do have options though:
You could set the DataCOntext of the view to itself, then expose each viewmodel through a separate property and bind to those properties:
public class MyView : Window
{
public MyView()
{
this.DataContext = this;
}
public ViewModel1 FirstViewModel { get; set; }
public ViewModel2 SecondViewModel { get; set; }
}
Or you could make a wrapper viewmodel which either extends (inherits from) one of the viewmodels, or wraps them both and surfaces the appropriate properties:
public class MyCompositeViewModel
{
public ViewModel1 FirstViewModel { get; set; }
public ViewModel2 SecondViewModel { get; set; }
}
You can set the DataContext for each DataGrid rather than for the container view.
<Grid>
<DataGrid ... DataContext="..." />
<DataGrid ... DataContext="..." />
</Grid>
Or don't use a DataContext and Bind to the models directly
<DataGrid ItemsSource="{Binding Source={StaticResource ...}}" />
I have a WPF combobox that I would like to bind to an observable collection of Teams on my ViewModel class e.g.
class Team
{
public int Id { get; set; }
public string Name { get; set; }
public int CountryId { get; set; }
}
class ViewModel
{
public ObservableCollection<Team> Teams { get; set; }
public IDictionary<int, Image> CountryFlags { get; set; }
}
I'd like to have the combobox display the flag and name of each team, what is the best way to do this?
I don't want to add the image directly to the team object if I can avoid it and would be happy to move the CountryFlags lookup to another class if need be.
You'll need to make a custom IValueConverter for this. Basically, you'll want to have the converter convert from Team -> Image, and have it do the lookup within the Dictionary based on the CountryId in the Team.