Currently I'm coding pretty much with WPF Applications in MVVM style.
I want to extend my current BaseViewModel with some new stuff that makes things easier and faster.
One functionality I want to add is to observe all properties (with a specific attribute) and call the PropertyChanged event when the property is changed by default.
(This functionality is more about laziness, so it's not that important but I don't know how to accomplish this)
Currently I define a properties in the subclass like this:
private string _foo;
public string Foo
{
get { return _foo; }
set { _foo = value; OnPropertyChanged(); }
}
I plan to define (because it's faster and less code) the properties like this:
[Observe]
public string Foo { get; set; }
Is there any valid way to call the property changed event by default for every "marked" property in each sub class when the "set" method is called?
You probably want to take a look at Fody.
It injects INotifyPropertyChanged code into properties at compile time.
Related
I have a abstract class ...
public abstract class MyClass
{
// other properties
public bool IsTypeDefault {get;set;}
}
I have a number of other classes that inherit from MyClass, say, MyClassA, MyClassB, MyClassC, etc.
And I have a collection class defined as ...
public class MyCollection : List<MyClass>
{
public SetAsTypeDefault(MyClass item)
{
}
}
The method SetAsTypeDefault should take an object of type MyClass, it will search the collection for a items of the same specific type, unset the IsTypeDefault on any item it finds where that value is true and then set it as true for the item that matches the passed in parameter.
What I want is to stop someone from setting the IsTypeDefault value on an individual instance of the collection directly and I can't figure out how to do it.
I can make IsTypeDefault readonly, but then I can't set it from the collection class. I can set it as private set and have a method set it, but the method needs to be public to be callable from the collection.
I'm only going to the bother of trying to do this 'cos the devs accessing this class are going to be completely out of my control. Nor am I going to be able to review their code and I want to make sure that they don't mess things up.
I appreciate that there I can't stop them from deliberately breaking stuff, for example, using reflection, but if they do this I want it to be because they are doing it on purpose rather than just being careless.
Is it possible?
A post-Post thought
I suppose I could attach an event to the IsTypeDefault property and have the collection class subscribe to the event, have it (the collection) do the verification before allowing (or not) the change to the instance in the collection. Yes?
If both MyCollection and MyClass are within the same assembly, but the developers using it are not - then its a simple case of making the setter internal
public abstract class MyClass
{
// other properties
public bool IsTypeDefault {get; internal set;}
}
After a major edit to this quesiton, I'm hoping it's now clear.
I'm very lost with binding in WPF when 1 change should affect multiple properties.
I regularly use VVM to bind my ViewModel to my View and I would say I'm OK with it.
I am trying to implement a state controller. This means that, what ever settings I made in part of my UI, the reflection is through out.
For example in my part of my UI, I can toggle a feature on or off, such as "show images"
When I make this change, I'd like everything in my application to be notified and act accordingly.
So, my StateController class will have a property
public bool ShowImages
And in my View, I'd likely have something like
<image Visible ="{Binding ShowImages", Converter={StaticConverter ConvertMe}}" />
The problem I have is how I go about making the StateController alert all of my ViewModels of this.
Currently, in each ViewModel I'm assuming I'd have to have the same property repeated
public bool ShowImages
EG
public class StateController : BaseViewModel
{
public bool ShowImages{get;set;}//imagine the implementation is here
}
public class ViewModelB : BaseViewModel
{
public bool ShowImages{}//imagine the implementation is here
}
public class ViewModelB : BaseViewModel
{
public bool ShowImages{}//imagine the implementation is here
}
So, my question is, if I updated ViewModelB.ShowImages, how would I first inform the StateController which in turn updates all ViewModels.
Is this something the INotifyPropertyChanged can do automatically for me since they all share the same propertyName, or do I have to implement the logic manually, eg
public static class StateController
{
public bool ShowImages{get;set;}//imagine the implementation is here
}
public class ViewModelA : BaseViewModel
{
public bool ShowImages
{
get { return StateController.ShowImages; }
set { StateControllerShowImages = value;
OnPropertyChanged("ShowImages"); }
}
}
public class ViewModelB : BaseViewModel
{
public bool ShowImages
{
get { return StateController.ShowImages; }
set { StateControllerShowImages = value;
OnPropertyChanged("ShowImages"); }
}
}
I hate the idea of the above implementation but it does show what I'm trying to achieve. I just hope there is a better way!
The PropertyChange notification is only raised for that one object model.
So raising a change notification of the "Name" property of ClassA will only update the UI in cases where it's bound to that specific ClassA.Name. It won't trigger a change notification for any ClassB.Name, or other instances of ClassA.Name.
I would suggest using a Singleton here for your StateModel, and having your other models subscribe to the StateModel.PropertyChanged event to know if it should update, like this answer.
public ViewModelA
{
public ViewModelA()
{
StateController.Instance.PropertyChanged += StateController_PropertyChanged;
}
void StateController_PropertyChanged(object sender, NotifyPropertyChangedEventArgs e)
{
// if singleton's ShowImages property changed, raise change
// notification for this class's ShowImages property too
if (e.PropertyName == "ShowImages")
OnPropertyChanged("ShowImages");
}
public bool ShowImages
{
get { return StateController.Instance.ShowImages; }
set { StateController.Instance.ShowImages = value; }
}
}
If I understood you correctly, you are looking for a mechanism that allows your different ViewModels to communicate between each other.
One possible way would be to implement the Observer Pattern (a code example can be found here: "Observer pattern with C# 4"). In this way your ViewModel subscribe each other to receive change notifications from a "publisher", i.e. the ViewModel that had its value changed. You have a good control over who receives which notification from which publisher. The downside of this approach is a tight coupling between your models.
My approach would be this:
Use a message dispatcher. Your ViewModels can subscribe to a certain type of message, e.g. ShowImagesChanged. If any of your ViewModels changed the ShowImages property, that ViewModel calls the dispatcher to send out such a ShowImagesChanged message with your current values.
This way you can keep you ViewModels decoupled from each other. Still, although the ViewModels do not know each other this gives a way to exchange data between them.
Personally, I have used the Caliburn Micro MVVM framework several times for this, but there should be enough other MVVM frameworks that provide the same functionality to fit your taste.
The Calibiurn Micro documentation and how easily the dispatcher can be used is here: Event Aggregator
To avoid code repetition you can create a class derived from BaseViewModel that implements your property and have ViewModelA, ViewModelB extend it. However, this does not solve the problem of keeping each instance updated.
In order to do so, you may:
Use a static class (your current solution) or a Singleton as suggested in one of the comments. This is simple but has potential problems such as race conditions and coupling.
Have your ShowImages binding property repeated in each ViewModel and update it by subscribing to a ShowImagesChanged event. This could be published through a Command executed from the UI. I'd say this is the WPF approach and has the benefit of decoupling the ShowImages state management from its consumption.
Assign the ShowImagesupdate responsibility to a single ViewModel and subscribe to the its PropertyChanged in the other ViewModels so that they update accordingly. Better than the first option, but still huge coupling.
Why repeat properties at all? Just bind to StateController itself.
Say we have singleton StateController:
public class StateController : INotifyPropertyChanged
{
private static StateController instance;
public static StateController Instance {
get { return instance ?? (instance = new StateController()); }
}
//here`s our flag
private bool isSomething;
public bool IsSomething
{
get { return isSomething; }
set
{
isSomething = value;
PropertyChanged(this, new PropertyChangedEventArgs("IsSomething"));
}
}
private StateController(){}
public event PropertyChangedEventHandler PropertyChanged = delegate { };
}
Then in base VM class just make a reference to this controller:
public StateController Controller { get { return StateController.Instance; } }
And where needed bind like this:
<CheckBox IsChecked="{Binding Controller.IsSomething}">
Test
</CheckBox>
This way every binding will work with one property and react to one property. If you need some custom code to work you can subscribe to PropertyChanged of StateController where needed and take action.
I have a class that instantiates two classes which implement interfaces. I want one class to notify another class that something is OK. I could do it with an Action and then use private variables in the class but wondered if there was a direct way of doing it with properties so that when a property's value changes it updates a property on another class.
For example:
public class MyClass
{
public ILogger Logger {get;set;}
public ILogic Logic {get;set;}
private Form MyWinform;
public void Setup()
{
MyWinform = new MyWinform();
MyWinform.StartBatch += Logger.CreateFile; //Create file when user presses start
//How can I set a property on ILogic to be AllOk once ILogger says so??
//I could use an Action so that once all is ok I call IDecidedAlOK in ILogger which
//can then assign a private bool variable inside the class
Logic.ItsOKMethodSoSetVariableToTrue = Logger.IDecidedAllOKMethod;
}
public void DataIn(string Value)
{
Logic.DataIn(Value);
}
public void CreateInstances()
{
Logger = new FileLogger();
Logic = new MyLogic();
}
}
public class MyLogic : ILogic
{
public void DataIn(string Value)
{
//I want to check that all is ok before I do anything
//if (!AllOK)
//return;
//Do stuff
}
}
Implement INotifyPropertyChanged interface and subscribe to PropertyChanged event
I feel like it might be a bit more conventional to have your ILogger interface expose something like a "FileCreated" or "Ready" event, and allow your application to handle that event in order to update the ILogic object (or do whatever else is necessary).
EDIT: my apologies, after re-reading the question, I think I misunderstood what you were asking for.
There isn't any "natural" object that does exactly what you're asking, but you could create an anonymous delegate (or lambda expression) for this purpose:
Action<bool> loggerResult = (value) => Logic.ItsOKMethodSoSetVariableToTrue = value;
A property internally consists of two private methods, a get_XXX and a set_XXX, so unless you want to fetch the MethodInfo of those methods and invoke them (which are again methods) you have no choice but to implement a method calling approach.
Subscribing to event (INotifyPropertyChanged or some custom one) is OK, so is the method to pass a lambda-setter, but in some cases it might be more convinient to use a shared context object (much like the shared memory concept):
class ConversationContext
{
public bool EverythingIsOK { get; set;}
}
This object is passed to all interested objects (ILogic and ILogger) and they operate directly on it, instead of some internal properties. If change notifications are required, Implement INotifyPropertyChanged on it.
One positive aspect of this approach is that you won't get tangled in repeatedly firing events triggering other events and so on. A single object will hold the current state and no recurrent updates are needed.
Again, this is just one of many options.
I've got a lot of entity classes, and now in all properties of the entity classes need to add new functionality (call some method) in the getters and setters. What i want to say looks like this:
public class PersistentClass : BaseClass {
private string attr1;
[Persistent]
public string Attr1
{
get
{
//need to call here base class method
//refreshContents();
return attr1;
}
set
{
//need to call here base class method
//refreshContents();
attr1 = value;
}
}
private SomeObject attr2;
[Persistent]
public SomeObject Attr2
{
get
{
//need to call here base class method
//refreshContents();
return attr2;
}
set
{
//need to call here base class method
//refreshContents();
attr2 = value;
}
}
private List<SomeOtherObhect> details;
[Persistent]
pubic List<SomeOtherObject> Details
{
get
{
//need to call here base class method
//refreshContents("details");
return details;
}
set
{
//need to call here base class method
//refreshContents("details");
details = value;
}
}
}
For different types of fields i need to call different methods e.g. refreshContents() and refreshContetns("fieldName"). I'm looking to solve problem with IoC and Dependency Injection.
Could you help me please?
This seems like a use case for Aspect Oriented Programming (AOP).
Here are some links to start with:
Introduction to Aspect Oriented
Programming
And some examples
What will IoC or DI do in your case?
i think you just want a generic method in base class and call thios method from getters or setters
If you want to keep your refresh logic at one place, and call it differently from your properties, consider implementing INotifyPropertyChanged and handling the PropertyChanged event in your entity class itself and implement the refresh logic there.
However, More important question is why do you want to refresh the contents when a property is set or get? It might help to understand if you provide some real property names.
I have a abstract class called WizardViewModelBase.
All my WizardXXXViewModel classes inherit from the base abstract class.
The base has a property with a getter. Every sub class needs and overrides that string
property as its the DisplayName of the ViewModel.
Only ONE ViewModel called WizardTimeTableWeekViewModel needs a setter because I have to set
wether the ViewModel is a timetable for week A or week B. Using 2 ViewModels like
WizardTimeTableWeekAViewModel and WizardTimeTableWeekBViewModel would be redundant.
I do not want to override the setter in all other classes as they do not need a setter.
Can I somehow tell the sub class it needs not to override the setter?
Or any other suggestion?
With interfaces I would be free to use getter or setter but having many empty setter
properties is not an option for me.
Funny.. I have just thought what would happen if I really would need to SET all DisplayNames of the WizardPages contrary what I said firstly. Maybe I should not hardcode the strings in the getter and put the strings in a reesource file because of localization, then I need a setter anywhere in every sub class XD
Don't declare the setter method as virtual.
If for some reason (I can't think of one!) you need for it to be virtual at the top of your inheritance hierarchy then use sealed when you override it:
http://msdn.microsoft.com/en-us/library/aa645769(VS.71).aspx
If the property is not abstract, then any base class may choose to only override the setter, the getter, or both.
If you want your subclasses not to have access to your setter, except for only a given subclass, you can use the internal access modifier only to the getter, and implement classes that shouldn't have access to the setter in another assembly.
You should introduce a new abstract class, which will inhere WizardViewModelBase class. That class should override a property using both get and set accessors, but will leave a property abstract, like this:
public abstract string DisplayName
{
get;
set;
}
Then you can use this class as a base class for WizardTimeTableWeekViewModel class and you wil be able to override both get and set accessors.
I'd use a protected setter and create a seperate function to set the value. After all the class does not have the same interface as the others so distinguishing it visibly from the others should help readability.
class Base
{
public String Value { get; protected set; }
}
class SpecialChild : Base
{
public void SetValue(String newValue) { this.Value = newValue; }
}
// Somewhere else
SpecialChild special = foo as SpecialChild;
if (special != null)
{
special.SetValue('newFoo');
}
else
{
foo.DoSomeStuff();
}