I've a class like this:
public class PersonViewModel : ViewModelBase //Here is the INotifyPropertyChanged Stuff
{
public PersonViewModel(Person person)
{
PersonEntity = person;
}
public Person PersonEntity {
get { return PersonEntity.Name; }
private set { PersonEntity.Name = value; RaisePropertyChanged("PersonEntity");
}
public string Name {
get { return PersonEntity.Name; }
set { PersonEntity.Name = value; RaisePropertyChanged("Name");
}
public int Age{
get { return PersonEntity.Age; }
set { PersonEntity.Age= value; RaisePropertyChanged("Age");
}
public void ChangePerson(Person newPerson)
{
//Some Validation..
PersonEntity = newPerson;
}
My TextBoxes are bound to Name and Age of the ViewModel.
If I change the _person object in the ViewModel, do I have to call for each Property a RaisePropertyChanged again or is there a way to do this automaticly (in my concret example I have about 15 Properties..)?
Thanks for any help.
Cheers
Joseph
You can indicate all properties have changed by using null or string.Empty for the property name in PropertyChangedEventArgs. This is mentioned in the documentation for PropertyChanged.
One other solution I used to tackle the problem of: first setting the value and then calling the PropertyChangedEventArgs is by adding a Set function in my ViewModelBase which looks like this:
public class ViewModelBase : INotifyPropertyChanged
{
protected bool Set<T>(ref T backingField, T value, [CallerMemberName] string propertyname = null)
{
// Check if the value and backing field are actualy different
if (EqualityComparer<T>.Default.Equals(backingField, value))
{
return false;
}
// Setting the backing field and the RaisePropertyChanged
backingField = value;
RaisePropertyChanged(propertyname);
return true;
}
}
Instead of doing this:
public string Name {
get { return PersonEntity.Name; }
set { PersonEntity.Name = value; RaisePropertyChanged("Name");
}
You can now achieve the same by doing this:
public string Name {
get { return PersonEntity.Name; }
set { Set(ref PersonEntity.Name,value);
}
Related
I am trying to understand how to trigger all the properties update when new data available.
For example I have two properties:
public string PropertyOne
{
get
{
return _propertyOne
}
set
{
_propertyOne= value;
this.OnPropertyChanged();
}
}
public string PropertyTwo
{
get
{
return _propertyTwo;
}
set
{
_propertyTwo = value;
this.OnPropertyChanged();
}
}
When I receive notification about new data I assign my properties:
Mediator<ViewModelMessages>.Instance.Register(ViewModelMessages.OnNewData, this.OnNewData);
private void OnNewData(object obj)
{
PropertyOne = (MyClass)obj.propertyOne;
PropertyTwo = (MyClass)obj.propertyTwo;
}
What I want to have is something like this:
private MyClass _myClass;
private void OnNewData(object obj)
{
_myClass = (MyClass)obj;
}
public string PropertyOne
{
get
{
return _myClass.PropertyOne;
}
set
{
_myClass.PropertyOne = value;
this.OnPropertyChanged();
}
}
public string PropertyTwo
{
get
{
return _myClass.propertyTwo;
}
set
{
_myClass.propertyTwo = value;
this.OnPropertyChanged();
}
}
So when new data arrived, my properties are automatically updated.
You can achieve that by passing an Empty string or null to your OnPropertyChanged rather than a property name, but note that property changed will get raised for all properties in this case.
EDIT: This is a Windows Store (8.1) application
I have a person class as shown below which I am using as a model
public class Person : BaseModel
{
private string _FirstName;
public string FirstName
{
get { return _FirstName; }
set
{
if (_FirstName == value)
return;
_FirstName = value;
RaisePropertyChanged("FirstName");
}
}
private string _MiddleName;
public string MiddleName
{
get { return _MiddleName; }
set
{
if (_MiddleName == value)
return;
_MiddleName = value;
RaisePropertyChanged("MiddleName");
}
}
private string _LastName;
public string LastName
{
get { return _LastName; }
set
{
if (_LastName == value)
return;
_LastName = value;
RaisePropertyChanged("LastName");
}
}
}
where BaseModel is defined as below
using GalaSoft.MvvmLight;
public class BaseModel: ObservableObject
{
}
I am using the Model in a ViewModel class as shown below.
using GalaSoft.MvvmLight;
public class PersonViewModel : ViewModelBase
{
/// <summary>
/// List of searched People
/// </summary>
private ObservableCollection<Person> _People;
public ObservableCollection<Person> People
{
get { return _People; }
set
{
if (_People== value)
return;
_People= value;
RaisePropertyChanged("People");
}
}
}
I am binding the People collection to a GridView as shown below.
<GridView
x:Name="PeopleSearchResultsGridView"
ItemsSource="{Binding People}">
</GridView>
When the search completes I get back a list of people which I add to the list as follows.
var list = await p.SearchPeople();
People = new ObservableCollection<Person>(list);
I see that the setter for the People collection is firing and the RaisePropertyChanged("People") event is also firing however that is not updating the GridView. Can anyone tell me what is wrong here ?
How can override the type of View property to my custom type.
My CustomGroupListCollectionView type adds extra property to the Groups property.
During runtime when i observe the type of View property is ListCollectionView, i want to change this to CustomGroupListCollectionView.
public class CollectionViewSourceCustom : CollectionViewSource
{
public new CustomGroupListCollectionView View { get; set; }
}
public class CustomGroupListCollectionView : ListCollectionView
{
private readonly CustomGroup _allGroup;
public CustomGroupListCollectionView(IList list)
: base(list)
{
_allGroup = new CustomGroup("All");
foreach (var item in list)
{
_allGroup.AddItem(item);
}
}
public override ReadOnlyObservableCollection<object> Groups
{
get
{
var group = new ObservableCollection<object>(base.Groups.ToList());
group.Add(_allGroup);
return new ReadOnlyObservableCollection<object>(group);
}
}
}
public class CustomGroup : CollectionViewGroup
{
public CustomGroup(object name)
: base(name)
{
}
public void AddItem(object item)
{
ProtectedItems.Add(item);
}
public override bool IsBottomLevel
{
get { return true; }
}
bool _IsChecked;
public bool IsChecked
{
get { return _IsChecked; }
set { _IsChecked = value; }
}
Visibility _CheckBoxVisibility;
public Visibility CheckBoxVisibility
{
get { return _CheckBoxVisibility; }
set { _CheckBoxVisibility = value; }
}
bool _IsExpanded;
public bool IsExpanded
{
get { return _IsExpanded; }
set { _IsExpanded = value; }
}
Visibility _ExpanderVisibility;
public Visibility ExpanderVisibility
{
get { return _ExpanderVisibility; }
set { _ExpanderVisibility = value; }
}
Visibility _ImageVisibility = Visibility.Collapsed;
public Visibility ImageVisibility
{
get { return _ImageVisibility; }
set { _ImageVisibility = value; }
}
}
CollectionViewSource has a CollectionViewType property, which you can use to determine the type of CollectionView the CollectionViewSource returns, like
<CollectionViewSource x:Key="source" CollectionViewType="{x:Type my:CustomGroupListCollectionView}" Source="{Binding MyData}"/>
As you see, you don't even have to create a new CollectionViewSource class.
If you still persist on using your way I would suggest this code:
public class CollectionViewSourceCustom : CollectionViewSource
{
public CollectionViewSourceCustom()
: base()
{
((ISupportInitialize)this).BeginInit();
this.CollectionViewType = typeof(CustomGroupListCollectionView);
((ISupportInitialize)this).EndInit();
}
}
Hope it helps.
Currently I want the calculations to be dynamic and change on per key stroke. I am trying to do this using MVVM but not entirely sure how.
In the view Model:
public int? Duration { get { return _seb.Duration; } set { _seb.Duration = value;} }
public decimal? Amount { get { return _seb.AmountPer; } set { _seb.AmountPer = value;} }
I have a total Variable And would like it to be constantly updated. May I ask how do I do this.
I tried something like this but no luck
public decimal? Total {get { return _seb.Total; } set { _seb.Total = Amount*Duration; }}
This can be done by raising the ProperyChanged event of the total property when either of the other two property changes.
public class SomeViewModel : ViewModelBase
{
private int? _duration;
private decimal? _amount;
public int? Duration
{
get { return _duration; }
set
{
if (_duration != value)
{
_duration = value;
RaisePropertyChanged("Duration");
RaisePropertyChanged("Total");
}
}
}
public decimal? Amount
{
get { return _amount; }
set
{
if (_amount != value)
{
_amount = value;
RaisePropertyChanged("Amount");
RaisePropertyChanged("Total");
}
}
}
public decimal? Total
{
get
{
if (Amount.HasValue && Duration.HasValue)
return Amount.Value * Duration.Value;
return null;
}
}
}
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
You must implement INotifyPropertyChanged and put the formula on get of the total property
public int? Duration
{
get
{
return _seb.Duration;
}
set
{
_seb.Duration = value;
this.RaisePropertyChanged("Total")
}
}
You should show your xaml view as well.
Assuming you are using a textbox, bound to some property in your ViewModel, you can make sure that that property is updated whenever the textbox propery changes by doing something like this:
<TextBox Text={Binding MyVmProperty, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged} />
In .NET I have a class called Caption. I have another class called Gauge. Within the Gauge class I have a property defined as a Caption.
I am trying to figure out how to do the following:
When a certain property is changed in my Caption class how do I get it to execute a subroutine in the Gauge class? I am thinking I have to declare an event and AddHandlers to fire it off, but I can't think of how to accomplish this.
You'll want to look at implementing the INotifyPropertyChanged interface, which is designed exactly for the purpose - raising an event when a property of a class instance changes.
A good example of usage is given on this MSDN page.
// This class implements a simple customer type
// that implements the IPropertyChange interface.
public class DemoCustomer : INotifyPropertyChanged
{
// These fields hold the values for the public properties.
private Guid idValue = Guid.NewGuid();
private string customerName = String.Empty;
private string companyNameValue = String.Empty;
private string phoneNumberValue = String.Empty;
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(String info)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(info));
}
}
// The constructor is private to enforce the factory pattern.
private DemoCustomer()
{
customerName = "no data";
companyNameValue = "no data";
phoneNumberValue = "no data";
}
// This is the public factory method.
public static DemoCustomer CreateNewCustomer()
{
return new DemoCustomer();
}
// This property represents an ID, suitable
// for use as a primary key in a database.
public Guid ID
{
get
{
return this.idValue;
}
}
public string CompanyName
{
get {return this.companyNameValue;}
set
{
if (value != this.companyNameValue)
{
this.companyNameValue = value;
NotifyPropertyChanged("CompanyName");
}
}
}
public string PhoneNumber
{
get { return this.phoneNumberValue; }
set
{
if (value != this.phoneNumberValue)
{
this.phoneNumberValue = value;
NotifyPropertyChanged("PhoneNumber");
}
}
}
}
public class Caption
{
private int myInt;
public event EventHandler MyIntChanged;
private void OnMyIntChanged()
{
var handler = this.MyIntChanged;
if (handler != null)
{
handler(this, EventArgs.Empty);
}
}
public int MyInt
{
get
{
return this.myInt;
}
set
{
if (this.myInt != value)
{
this.myInt = value;
this.OnMyIntChanged();
}
}
}
}
So now, in your guage class:
public class Guage
{
private Caption caption;
public Caption Caption
{
get
{
return this.caption;
}
set
{
if (this.caption!= value)
{
this.caption= value;
this.caption.MyIntChanged += new EventHandler(caption_MyIntChanged);
}
}
}
private void caption_MyIntChanged(object sender, EventArgs e)
{
//do what you gotta do
}
}