C# Cast Class to Overridden Class - c#

I have a class Application that I need to override with INotifyPropertyChanged events. I have written the logic to override the original class and ended up creating SuperApplication
I am pulling the data from a library though, and cannot change the loading logic. I just need a way to get the data from the original class into my superClass. I've tried things like superClass = (SuperApplication)standardClass; but it hasn't worked.
How would I go about doing this?
If it helps, this is the code I'm using to override the original class:
public class SuperCreditApplication : CreditApplication
{
public SuperCreditApplicant Applicant { get; set; }
public SuperCreditApplicant CoApplicant { get; set; }
}
public class SuperCreditApplicant : CreditApplicant
{
public SuperProspect Prospect { get; set; }
}
public class SuperProspect : Prospect, INotifyPropertyChanged
{
public State DriverLicenseState
{
get
{
return DriverLicenseState;
}
set
{
DriverLicenseState = value;
OnPropertyChanged("DriverLicenseState");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

It sounds like you should use a copy constructor, passing in "the data from the original class" as a parameter to a newly-constructed superClass (Incidentally, I think the name Super- is probably a mistake, as that will make people think that it's above the original in the hierarchy).
By copy-constructor, I mean something like:
class IWishIWasntCalledSuperApplication : Application
{
IWishIWasntCalledSuperApplication(Application original)
{
this.someData = original.someData;
this.someOtherData = original.someOtherData;
...etc...
}
}

I assume that you can't just implement INotifyPropertyChanged directly on Prospect. If you cannot directly change Prospect (like make all your properties virtual), you can make your SuperProspect class a wrapper for Prospect
public class SuperProspect : INotifyPropertyChanged
{
private readonly Prospect _prospect;
public SuperProspect(Prospect prospect)
{
_prospect = prospect;
}
public State DriverLicenseState
{
get { return _prospect.DriverLicenseState; }
set
{
_prospect.DriverLicenseState = value;
OnPropertyChanged("DriverLicenseState");
}
}
public void SomeMethod()
{
_prospect.SomeMethod();
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
You can then use SuperProspect like this
var superProspect = new SuperProspect(myProspect);
If you create an interface for your Prospect members, then you can make both your SuperProspect and your Prospect implement the same interface. If you then program to the interface rather than the concrete Prospect implementation, your code will work with both SuperProspect and/or Prospect.

You didn't say whether the load was during the construction of the object or a later method call. Depending on which, it would look like one of these two code samples.
//This constructor signature should match your base class's
public SuperCreditApplication(object a, object b, object c) : base(a,b,c)
{
//Do whatever you need to do here. The base object's constructor will be called for you
}
public Load()
{
this.BaseObjectLoadMethod();
}
Then you make a new SuperCreditApplication and work with that.

Given your comment and edit I need to give a new answer lol - i misunderstood
you need to use interception to add the event handlers to the properties over which you have no control maybe. Personally I ahve seen this done with IoC containers such as prism. I may be completley wrong here btw but i think MEF may also help
Another way would be to look into code generation using T4 templates to reflect over the existing class to generate your superclass and the properties that map onto 4existing that would contain the code to fire the events.
this looks like it
http://lostechies.com/derekgreer/2009/03/01/implementing-inotifyproperychanged-with/
To explain the MEF thing: I am pretty sure i have seen INotifyPropertyChanged hooked up using MEF in various silverlight examples. I wasn't interested in that aspect when i was reading though so didn't read up on it.
Extracting an interface and using an ioc container to do all the heavy lifting would be the shortest route i imagine.

Related

Percolate data through properties

I've got a class with a list of properties, and the properties themselves have a list of properties. I need the "grandchild"- property to be able to request data from it's parent's parent (sorry for the confusing terms - there's no inheritance here). To clarify:
class ClassA
{
list<ClassB> Children
var SomeOtherProperty
}
class ClassB
{
list<ClassC> Grandchildren
}
class ClassC
{
var GetSomeOtherProperty()
{
...
}
}
The data may change during run time so I can't just pass it once and be done with it, I gotta be able to get it dynamically.
I could always pass the parent all the way down to the grandchild in the ctors, but I was taught it's a bad practice, so I'd rather avoid it.
I've been reading about passing data back/downwards via events using mutable EventArguments- I'm wondering if that'd be an OK solution for what I've got (I'll need to do it twice each time- sort of chase the tail of the first eventarg). Are there any pitfalls I need to be aware of?
Do I have any other options for this situation?
Thanks!
If possible, you can use the design pattern composite. First, create a base class 'note' with a list of notes for the children and a virtual method 'DoAction'. Then derive all other classes from this class and override the method with own implementation.
Now you can build up a tree of notes and do a traversal on all of it childs. For each of them, call 'DoAction'.
Hope you get the idea...
Since classes A, B & C are not liked via inheritance, therefore, I would like to avoid any direct wiring between these classes as it will make the design a little complicated as the system would evolve.
Moreover, since class B has nothing to do with the data, I dont want it to get effected by it.
Therefore, I would like to take out the communicate via a separate route to keep the classes loosely coupled -
here is a sample code to explain my idea -
public interface IPublisher
{
event EventHandler OperationOccurred;
}
class ClassA : IPublisher
{
List<ClassB> Children;
event EventHandler OperationOccurred;
public ClassA()
{
BroadCaster.Instance.RegisterPublisher(this);
}
protected virtual void OnOperationOccurred()
{
if (OperationOccurred != null)
OperationOccurred(this, new EventArgs());
}
}
class ClassB
{
List<ClassC> Grandchildren;
}
class ClassC
{
public ClassC()
{
BroadCaster.Instance.BroadCastNotificaiton += Instance_OperationOccurred;
}
void Instance_OperationOccurred(object sender, EventArgs e)
{
throw new NotImplementedException();
}
}
/// <summary>
/// A singleton class ... Like a single braodcast tower just one in the city
/// </summary>
public sealed class BroadCaster
{
public static BroadCaster Instance { get; private set; }
//Static constructor
static BroadCaster()
{
Instance = new BroadCaster();
}
// private constructor
private BroadCaster(){}
public event EventHandler BroadCastNotificaiton;
public void RegisterPublisher(IPublisher publisher)
{
publisher.OperationOccurred += Publisher_OperationOccurred;
}
void Publisher_OperationOccurred(object sender, EventArgs e)
{
if (this.BroadCastNotificaiton != null)
this.BroadCastNotificaiton(sender, e);
}
}
I have implemented broadcaster a singleton object, but all I want to convey is a single point of communication.
Hope it helps.

How to update WPF binding from a helper class

I'm sure this is a very basic question but I don't even know the technical term / jargon to Google and self-educate on.
I have created a simple model implementing INotifyPropertyChanged.
public class PushNotes : INotifyPropertyChanged
{
public string CompletePushNotes { get; set; }
}
Binding in cs:
evt_pushNotes = new PushNotes()
{
CompletePushNotes = "HelloThere"
};
this.DataContext = evt_pushNotes;
//snip later in code
Helpers.UpdateCompletePushNotes();
In XAML:
<xctk:RichTextBox x:Name="PushEmail" Text="{Binding Path=CompletePushNotes, Mode=OneWay}" ScrollViewer.VerticalScrollBarVisibility="Auto" Margin="40,398,40,40">
<xctk:RichTextBox.TextFormatter>
<xctk:PlainTextFormatter />
</xctk:RichTextBox.TextFormatter>
</xctk:RichTextBox>
Helper:
internal static class Helpers
{
internal static void UpdateCompletePushNotes()
{
//duhhhh what do I do now??
//If I create a new PushNotes it will be a different instantiation....???
}
}
Now this is all fine but I have a method in a helper class that needs to change the CompletePushNotes.
Again I know this is a simplistic / newbie question but I don't know what I need to learn.
So do I make my PushNotes class static, or singleton. Is there some global binding "tree" I can walk to find my instantiated and bound PushNotes class that is attached to the UI element?
Not looking for an a handout just need to know what it is I'm looking for.
TIA
Your PushNotes class does not implement the INotifyPropertyChanged interface. Once you have implemented it, you need to modify your CompletePushNotes property to have a backing field and in the setter of the property you can raise the PropertyChanged event to notify the UI of the source property update.
public class PushNotes : INotifyPropertyChanged
{
string completePushNotes;
public string CompletePushNotes
{
get
{
return completePushNotes;
}
set
{
completePushNotes = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Making the PushNotes class static will not help you. You seem to have a variable of some sort to the PushNotes instance (evt_pushNotes), so just do:
evt_pushNotes.CompletePushNotes = something;
If you have a helper class that does something, call the method in the helper class and get the value back or pass the PushNotes instance into the helper class as a parameter.
internal static class Helpers
{
internal static void UpdateCompletePushNotes(PushNotes pushNotes)
{
pushNotes.CompletePushNotes = something;
}
}

MVVM shared properties

There are some similar questions on SO, but they weren't quiet the same, so I'm posting this instead. I'm new to MVVM, so I'm trying to figure out how I can create a class that can hold properties that can be shared among views. So, if I set a property in one view, all the other views would get notified if its changed and would adjust their properties accordingly.
What I have now is rather very crude and is definitely not something I want to use. This is my common class that will hold all the properties:
public static class Common
{
private static string _title;
public static string Title
{
get { return _title; }
set
{
if (_title == value)
{
return;
}
_title = value;
OnPropertyChanged("Title");
}
}
public static void Load()
{
// set properties here
}
public static event PropertyChangedEventHandler PropertyChanged;
private static void OnPropertyChanged(string name)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(typeof(SettingsWorker), new PropertyChangedEventArgs(name));
}
}
}
...and I have to subscribe to it from each ViewModel:
Common.PropertyChanged += Common_PropertyChanged;
private void Common_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
Title = Common.Title;
}
But this is where the breakdown happens. I can get the property name from the PropertyChangedEventArgs, but I've no idea how to get the value. Therefore, I'm forced to update all the properties, and that can get nasty to maintain. The code is becoming a mess.
I'm basically trying to get properties that ViewModels can share. How can I accomplish this?
It looks like you just have some global data you want to show in multiple places. The most straightforward way to do this is to just make it like and normal ViewModel class and then make it available to each of your other ViewModels and expose it from them to bind to directly (rather than copying the property into each of them). You can do this using IOC, or make it available statically, more similar to how you have it now.
If you go the static direction, the key change you need to make is to use a singleton rather than a static class in order to allow property change notification to work. Bindings work with INPC on instances but not static classes. The Common class would look more like this:
public class Common : INotifyPropertyChanged
{
private static Common _instance = null;
protected Common()
{
}
public static Common GetInstance()
{
if (_instance == null)
_instance = new Common();
return _instance;
}
private string _title;
public string Title
{
get { return _title; }
set
{
if (_title == value)
return;
_title = value;
OnPropertyChanged("Title");
}
}
public void Load()
{
}
public virtual void OnPropertyChanged(string propertyName)
{
PropertyChangedEventArgs ea = new PropertyChangedEventArgs(propertyName);
if (PropertyChanged != null)
PropertyChanged(this, ea);
}
public event PropertyChangedEventHandler PropertyChanged;
}
There are a lot of different ways you can then use this. Here's one of the more direct ones:
public class SomeViewModel : ViewModelBase
{
public Common CommonData { get; private set; }
public SomeViewModel()
{
CommonData = Common.GetInstance();
}
}
Then in XAML you can bind to the properties from the common class and get change notification, even across the different VM usages.
<TextBox Text="{Binding Path=CommonData.Title}"/>
There's also the option of making the singleton accessible as a property and binding to it directly from XAML using x:Static but that's a little different direction that what you were asking.
So if you have other views that want to get notified when a property changes I would assume you have a separate viewmodel for each of those views. In that case what you would be asking for is "How can viewmodels talk to other viewmodels?" For a good learning experience, I would recommend looking into the observer pattern. If you don't like that style, then I would recommend you look into using a MVVM Framework like "SimpleMVVM, Catel, or many others" (Just need to look some up). Then once you have that framework in you project, I would create a baseviewmodel class that all your viewmodels will inherit. Once that is done you can take advantage of the frameworks messenger system. Basically it would look something like:
public YourViewModel()
{
RegisterToReceiveMessages(MessageTokens.SomeToken, OnChangeCallYourMethodToAddress); //The MessageTokens is something you generally create ur self.
}
#region Notifications
void OnChangeCallYourMethodToAddress(object sender, NotificationEventArgs<SlideShowLocale> e)
{
SomeProperty = e.Data;
}
Then to send a message to "YourViewModel" From another ViewModel:
public AnotherViewModel
{
SendMessage(MessageTokens.SomeToken, new NotificationEventArgs(WhateverYouWantToSend));
}
So basically, by declaring the token you want, it then finds the viewmodel that is registered with that token and listens for any messages to come in.

Using INotifyPropertyChanged in a Class

C# allows the creation of a property as below:
public string SomeRandomText
{
get; set;
}
The framework handles the creation of the backing variable for this property. How can I have such a property and still have change notification?
Is this allowed in a class that implements INotifyPropertyChanged?
public string SomeRandomTextBeingNotified
{
get;
set
{
NotifyPropertyChanged("SomeRandomTextBeingNotified");
}
}
You can't use automatic properties when trying to use this. You'll need to creating a backing store:
private string _someRandomText;
public string SomeRandomText {
get { return _someRandomText; }
set
{
_someRandomText = value;
NotifyPropertyChanged("SomeRandomText");
}
}
To make code look cleaner, you can use attributes for INotifyPropertyChanged.
Easy usage of INotifyPropertyChanged with Property-Attribute
Have a look at this Use of Attributes... INotifyPropertyChanged
Actually you can, but you basically need to change the bytecode post C# compiler.
This may sound like a lot of work, but this is one of the easier postprocessing steps that for example PostSharp includes.
http://www.sharpcrafters.com/solutions/notifypropertychanged
http://www.sharpcrafters.com/blog/post/Recording-Automate-INotifyPropertyChanged-with-Karol-Waledzik-from-Internetium.aspx
A lot more functionality is available ;)
Otherwise note that
enter code hereenter code here`NotifyPropertyChanged("SomeRandomTextBeingNotified");
is bad code. I do all that in one field update method:
set
{
OnUpateField (ref _someRandomText, value);
}
The update method does all - check for equality (you do NOT want to trigger when new value = old value), then trigger updates as needed. It gets the property name through the calling method third parameter that is automatically set by the compiler. Alternatives are using a LINQ statement ( ref someRandomText, value, this->SomeRandomText). I never would love a string there that does not get renamed on refactoring ;)
If you don't have a base class, something like this is cake and very flexible:
public class NotificationObject : INotifyPropertChanged
{
private readonly Dictionary<string, object> Properties = new Dictionary<string, object>();
public event PropertyChangedEventHandler PropertyChanged;
protected TType Get<TType>(string propertyName)
{
object value;
return Properties.TryGetValue(propertyName, out value) ? (TType)value : default(TType);
}
protected void Set<TType>(TType value, string propertyName, params string[] dependantPropertyNames)
{
Properties[propertyName] = value;
OnPropertyChanged(propertyName);
if (dependantPropertyNames != null)
{
foreach (string dependantPropertyName in dependantPropertyNames)
{
OnPropertyChanged(dependantPropertyName);
}
}
}
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArts(propertyName));
}
}
}
This can be used like this:
public SomeObjectThatNeedsToNotifySomething : NotificationObject
{
public int SomeValue
{
get { return Get<int>("SomeValue"); }
set { Set<int>(value, "SomeValue", "SomeAggregateValue"); }
}
public int SomeOtherValue
{
get { return Get<int>("SomeOtherValue"); }
set { Set<int>(value, "SomeOtherValue", "SomeAggregateValue"); }
}
public int SomeAggregateValue
{
get { return SomeValue + SomeOtherValue; }
}
}
If you already have a base class and need to just implement the INotifyPropertyChanged interface, #Rob is correct, provide a backing field and fire the event.
There is no such thing as semi-automatic properties. Nevertheless, there are quite a few ways to implement INotifyPropertyChanged that don't require the burdensome imperative code.
1) Mentioned before: PostSharp, an aspect oriented and commercial project.
2) Creating a Castle DynamicProxy solution. A sample can be found here, actually there's plenty of others out there.
It's worthwhile investing some time in a generic solution, the boilerplate code can get vexing after a while and is prone to errors.

Designing WPF classes for DataBinding

I have to build a chat app in WPF; I want to use DataBinding (still learning it) and want to do it in the right way. I've built a Buddy class in this way:
public class Buddy: INotifyPropertyChanged
{
private String _name;
private String _status;
public String Name
{
get
{
return _name;
}
set
{
_name = value;
NotifyPropertyChanged("Name");
}
}
public String Status
{
get
{
return _status;
}
set
{
_status = value;
NotifyPropertyChanged("Status");
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
I don't know which is the best way to handle BuddyList. Should I create a BuddyList class with Add and List method and then DataBinding to an instance of that class? What is the best way to do it?
You can use INotifyCollectionChanged Interface to create your BuddyListClass
Look here for an example: Usage of INotifyCollectionChanged
Also you can use ObservableCollection<T> Class.
If you want to bind collections of items you should use the
ObservableCollection class
and another suggestions create and base class that implement INotifyPropertyChanged interface,
and derive from it each class that you want to bind to UI.
I think your class definition looks just fine.
Regarding the list question I would expose my list as readonly for binding, and all the add, delete, edit functionality I would keep it private. To avoid informing manually your view for changes to your collection, I would use an ObservableCollection but exposing it to public as ReadOnlyObservableCollection.

Categories