|
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;
using ChainedObserver.WPFTest.DataHelper;
using CommonModel;
namespace ChainedObserver.WPFTest
{
/// <summary>
/// A simple ViewModel that demonstrates how the <c>ChainObserver</c> can be used
/// within a typical ViewModel. This ViewModel provides a lot of superflous properties
/// such as LastChanges/PersonChanges/AddressChanges/CityChanges for the View, that you
/// would not typically need, but they are simply here to aid the demo
/// </summary>
public class MainWindowViewModel : INotifyPropertyChanged
{
#region Data
private ObservableCollection<string> personChanges = new ObservableCollection<string>();
private ObservableCollection<string> addressChanges = new ObservableCollection<string>();
private ObservableCollection<string> geoLocationChanges = new ObservableCollection<string>();
private ObservableCollection<string> lastChanges = new ObservableCollection<string>();
private ChainPropertyObserver chainPropertyObserver;
#endregion
#region Ctor
public MainWindowViewModel()
{
MyPerson = new Person();
MyPerson.Age = 12;
MyPerson.Name = "sacha";
MyPerson.Address = new Address()
{
Addressline1 = "21 maple street",
Addressline2 = "Hanover",
GeoLocation = new GeoLocation { Longitude=0.5, Latitude=0.5 }
};
//create chainPropertyObserver
chainPropertyObserver = new ChainPropertyObserver();
chainPropertyObserver.CreateChain(() => MyPerson.Address.GeoLocation, Changed);
//And now hook up some specific Chain Listeners
chainPropertyObserver.RegisterChainLinkHandler(() => MyPerson,
() =>
{
personChanges.Add(MyPerson.ToString());
});
chainPropertyObserver.RegisterChainLinkHandler(() => MyPerson.Address,
() =>
{
addressChanges.Add(MyPerson.Address.ToString());
});
chainPropertyObserver.RegisterChainLinkHandler(() => MyPerson.Address.GeoLocation,
() =>
{
geoLocationChanges.Add(MyPerson.Address.GeoLocation.ToString());
});
//setup commands
ChangePersonCommand = new SimpleCommand<object,object>(ExecuteChangePersonCommand);
ChangeAddressCommand = new SimpleCommand<object, object>(ExecuteChangeAddressCommand);
ChangeGeoLocationCommand = new SimpleCommand<object, object>(ExecuteChangeGeoLocationCommand);
}
#endregion
#region Private Methods
private void Changed(string propertyThatChanged)
{
lastChanges.Add(propertyThatChanged);
}
#endregion
#region Public Properties
public ICommand ChangePersonCommand { get; private set; }
public ICommand ChangeAddressCommand { get; private set; }
public ICommand ChangeGeoLocationCommand { get; private set; }
public Person MyPerson { get; set; }
public ObservableCollection<string> LastChanges
{
get { return lastChanges; }
}
public ObservableCollection<string> PersonChanges
{
get { return personChanges; }
}
public ObservableCollection<string> AddressChanges
{
get { return addressChanges; }
}
public ObservableCollection<string> GeoLocationChanges
{
get { return geoLocationChanges; }
}
#endregion
#region Commands
/// <summary>
/// Do a simple one property change to Person
/// which should cause a single "Person" change
/// </summary>
private void ExecuteChangePersonCommand(object parameter)
{
MyPerson.Name = Jabberwock.RandomString();
}
/// <summary>
/// Show that the <c>ChainedObserver</c> is even ok with you setting new
/// objects (Address in this case) in the chain, it will be fine with that and pick up
/// the new object (Address in this case) just fine, and monitor the changes in that
/// using existing change handlers that were set up when the <c>ChainedObserver</c>
/// was 1st created
///
/// This command also changes a number of properties on a new Address just so that
/// the user can see that the <c>ChainedObserver</c> is indeed ok with new objects
/// being introduced into the chain.
/// </summary>
private void ExecuteChangeAddressCommand(object parameter)
{
Address currentAddress = MyPerson.Address;
GeoLocation currentGeoLocation = MyPerson.Address.GeoLocation;
//Should fire in this order
//1. MyPerson change, due to setting new Address on Person
//2. Address change, due to setting new Addressline1 on new Address (which starts out with empty property values)
//3. Address change, due to setting new Addressline2 on new Address (which starts out with empty property values)
//4. Address change, due to setting new Addressline3 on new Address (which starts out with empty property values)
//NOTE : That since we are effectively reusing the existing GeoLocation that the ChainedObserver already knows about
// assigning this to the new Address does not constitute a change, as IT IS THE SAME object, so no change
MyPerson.Address = new Address();
MyPerson.Address.Addressline1 = Jabberwock.RandomString();
MyPerson.Address.Addressline2 = currentAddress.Addressline2;
MyPerson.Address.Addressline3 = currentAddress.Addressline3;
MyPerson.Address.GeoLocation = currentGeoLocation;
}
/// <summary>
/// Do a simple one property change to GeoLocation
/// which should cause a single "GeoLocation" change
/// </summary>
private void ExecuteChangeGeoLocationCommand(object parameter)
{
MyPerson.Address.GeoLocation.Longitude = Jabberwock.RandomDouble();
}
#endregion
#region INotifyPropertyChanged event
///<summary>
///Occurs when a property value changes.
///</summary>
public event PropertyChangedEventHandler PropertyChanged;
/// <summary>
/// Raises the <see cref="PropertyChanged"/> event for
/// a given property.
/// </summary>
/// <param name="propertyName">The name of the changed property.</param>
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
#endregion
}
}
|
By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.
If a file you wish to view isn't highlighted, and is a text file (not binary), please
let us know and we'll add colourisation support for it.
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)
- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence
Both of these at Sussex University UK.
Award(s)
I am lucky enough to have won a few awards for Zany Crazy code articles over the years
- Microsoft C# MVP 2016
- Codeproject MVP 2016
- Microsoft C# MVP 2015
- Codeproject MVP 2015
- Microsoft C# MVP 2014
- Codeproject MVP 2014
- Microsoft C# MVP 2013
- Codeproject MVP 2013
- Microsoft C# MVP 2012
- Codeproject MVP 2012
- Microsoft C# MVP 2011
- Codeproject MVP 2011
- Microsoft C# MVP 2010
- Codeproject MVP 2010
- Microsoft C# MVP 2009
- Codeproject MVP 2009
- Microsoft C# MVP 2008
- Codeproject MVP 2008
- And numerous codeproject awards which you can see over at my blog