Value Object and View Model Property - wpf

I am working on a solution that used DDD for architecture. I have a property in my ViewModel which points to a ValueObject, the view model also implements INotifyPropertyChanged interface. The value of the ValueObject will change as a user enters data on the front end. The problem I am running into is the value object is suppose to be immutable. How can I work around this issue? Thank you in advance.

If you can edit something, then there must be a mutable container for the immutable value. Therefore, your viewmodel should act on the mutable container rather than on the immutable value directly.
An integer is an example of such an immutable value object: the Int32 type does not have any members that allow you to change the state of the object. You can only replace an integer, not change it. So a view model for an integer would look like this:
public MutableIntegerViewModel
{
private readonly mutableInteger;
public MutableIntegerViewModel(MutableInteger mutableInteger)
{
this.mutableInteger = mutableInteger;
}
public string DisplayText
{
get
{
return this.mutableInteger.Value.ToString(
CultureInfo.CurrentCulture);
}
set
{
this.mutableInteger.Value =
Int32.Parse(value, CultureInfo.CurrentCulture);
}
}
}
Where MutableInteger is just this:
public class MutableInteger
{
public int Value { get; set; }
}
I've omitted error handling and change notification here, but hopefully you get the idea.
Also note this example is not really different from the typical example of a Customer class with a FirstName and a LastName. Strings are also immutable, so again we have a mutable container for immutable values.

Related

Fill a combobox in WPF with a list of web services

I have a control like this:
<ComboBox x:Name="ComboTipo"
Height="23"
SelectionChanged="ComboTipo_SelectionChanged"
Width="450"
Canvas.Left="609"
Canvas.Top="26" />
And my code is:
ComboTipo.DisplayMemberPath = "Descripcion";
ComboTipo.SelectedValuePath = "IdTipoPersona";
ComboTipo.ItemsSource = myWebServices.dameTipos();
My web services returns a list for this object, this class is created in automatic when i add the reference to the web services:
public partial class TipoPersona {
private short idTipoPersonaField;
private string descripcionField;
/// <comentarios/>
public short IdTipoPersona {
get {
return this.idTipoPersonaField;
}
set {
this.idTipoPersonaField = value;
}
}
/// <comentarios/>
public string Descripcion {
get {
return this.descripcionField;
}
set {
this.descripcionField = value;
}
}
}
But the problem is:
The combobox displays the data types for each element of the list, and i want display the Descripcion.
Can you help me plis! Thanks
What does IdTipoPersona look like? Is it a class you created? If so, you may need to reference the property that you want displayed. It would look something like this:
ComboTipoPersona.SelectedValuePath = "IdTipoPersona.Text";
Where Text would be replaced by the property. It is really hard to judge otherwise what is going on with knowing a little more about the object structure that myWebServices.dameTipos() returns.
EDIT
Ok I was able to simulate your problem and simulate a solution as well.
Your issue is in the Tipos class. There are a couple of things necessary when binding to a combobox with a custom class.
First off, you will want to add accessors and mutators (getters and setters) to IdTippoPersona and Descripcion.
You should add a constructor that assigns to those properties with parameters.
It is usually a good idea to add a default constructor.
The finished code will look like this:
public class Tipos
{
public int IdTipoPersona { get; set; }
public string Descripcion { get; set; }
public Tipos(int id, string descripcion)
{
IdTipoPersona = id;
Descripcion = descripcion;
}
}
I found the asnwer if someone needs it.
We need create a class intermediate class but we were working with entity framework, for this way, we need add the intermediate class like complex type in my model (entity framework).
And also we need override this class.
And it works so well.
Thanks for all #Goody

Cast Observable Collection from base Class to inherited class

I'm writing a WPF application and I'm currently refactoring some reused code to a base ViewModel Class which my other viewmodels can inherit from.
One Property field on this base class is
public class MessageParentBase
{
MessageParentBase() {}
public string Name;
}
internal ObservableCollection<MessageParentBase> _GridData = new ObservableCollection<MessageParentBase>();
I have a subsequent property declaration
public ObservableCollection<MessageParentBase> GridData
{
get { return _GridData; }
set { _GridData = value; }
}
This works great and everything my issue is that the inerited classes actually use the follow class
Public class ChatMessage : MessageParentBase
{
public string Message;
}
and the view contains a grid of data which is bound to this GridData property but the column which should be bound to the Message field from the ChatMessage class is blank and the fields found in the MessageParentBase class are populated.
So I presume there is an issue with the view not knowing to cast up to the ChatMessage from the MessageParentBase class.
Can I inform the view that the objects will be of the type "ChatMessage".
I did try moving the property declaration up to the inherited viewmodel as
public ObservableCollection<ChatMessage> GridData
{
get { return _GridData; }
set { _GridData = value; }
}
but this gives me the following error:-
Cannot implicitly convert type 'System.Collections.ObjectModel.ObservableCollection' to 'System.Collections.ObjectModel.ObservableCollection'
Do I need to cast at the view level or can I change the viewmodels to implement this better?
Any suggestions would be greatly appreciated.
Emlyn
Change the collection to this:
public ObservableCollection<MessageParentBase> GridData { get; set; }
then add into your constructor
this.GridData = new ObservableCollection<MessageParentBase>();
Since WPF uses reflection to retrieve bound data from the data context it should be able to get the values of the derived classes stored in that collection.
Also when you run your application check the output window with Debug selected, the XAML engine will output any binding errors there.
Your ViewModel should contain a list with the type that your grid will show (in this case, the ChatMessage type). You can still use the inheritance to call common methods, but the binded list must be of the ChatMessage type

How should I pass property values from View to Model in MVVM?

I have three classes,
first:
public class Setting
which has properties:
string ID, string Value; (implements INotifyPropertyChanged on Value)
Second:
public class SettingCollection
which is a:
ObservableCollection<Setting>
Third:
public class SimObject
which has properties:
string ID, SettingsCollection Settings;
I have a View:
SettingsDisplay.xaml
which has dependency property:
SettingsCollection SimObjSettings;
and displays the setting's ID and with its Value in a TextBox inside an ItemsContainer.
My MainWindow ViewModel has a SimObject Jeff; and in the View I have
<local:SettingsDisplay SimObjSettings="{Binding Jeff.Settings}"/>
This all works fine.
I need to know when a Setting Value changes and when that happens I need to know the SimObject ID the Setting belongs to so that I can call a method that sends an event with the Setting ID, Value and the SimObject ID. (e.g. SendEvent(settingID, settingValue, targetObject))
Obviously Setting's and SettingCollection's have no knowledge of what SimObject they belong to.
The way I've tried to do this is in the Setting class call SendEvent in the Value property's Setter.
I'm struggling to find a suitable way to pass the SimObject's ID down the chain to the Setting's class, I also don't think this is a good solution.
What is the best way to acheive what I'm trying to do?
There are lots of ways to do this, but obviously all of them involve someone observing the SettingsCollection and dynamically attaching/detaching PropertyChanged handlers to all items inside it (at least that's what your requirements sound to me).
I would argue that if all you want is unconditional live updetes you should not involve the Views and ViewModels at all in this. Simply write an implementation of something like this:
interface ISimObjLiveUpdateService
{
void StartObserving(SimObject o);
bool IsObserving(SimObject o);
bool StopObserving(SimObject o);
}
The actual implementation would hook up to observe o.SettingsCollection and all items in it. Before you display a SimObject you StartObserving it, and when the view is closed you StopObserving it.
I ended up solving this by giving all Setting's a SimObject property, which was the setting's SimObject owner, and creating an event handler delegate void SettingHandler(string settingID, string settingValue, string targetObj);
in SimObject : public event SettingHandler SettingChanged;
public void RaiseSettingChangedEvent(string settingId, string settingValue, string targetObj)
{
if (SettingChanged != null)
{
SettingChanged(settingId, settingValue, targetObj);
}
}
In Setting on the string Value Setter:
set
{
_value = value;
RaisePropertyChanged("Value");
SimObject.RaiseSettingChangedEvent(ID, Value, SimObject.Settings["UID"].Value);
}
Then in SettingsDisplay I created a SelectedPropertyChangedCallback which adds the ParameterChanged event to the SimObject and also contains the SettingChanged method:
public void SettingChanged(string settingID, string settingValue, string targetObj)
{
Framework.GetBusinessDelegate().SendEvent(settingID, settingValue, targetObj);
}
Don't know how to add syntax highlighting to make this answer clearer.

Passing multiple parameters to Prism's EventAggregator

I'm using Prism's EventAggregator for loosely coupled communication between my module's ViewModels. I have have several properties (e.g. FirstName, LastName) in ViewModelA which need to update properties in ViewModelB when their values change. My current solution involves:
ViewModelA publishes an Event with the new value for FirstName as the payload:
public string FirstName
{
get {return firstName;}
set
{
this.firstName = value;
eventAggregator.GetEvent<PatientDetailsEvent>().Publish(firstName);
}
}
ViewModelB is subscribed to the Event and changes its FirstName property accordingly:
public PatientBannerViewModel(IEventAggregator eventAggregator)
{
this.eventAggregator = eventAggregator;
eventAggregator.GetEvent<PatientDetailsEvent>().Subscribe(UpdateBanner, ThreadOption.UIThread);
}
public void UpdateBanner(string firstName)
{
this.FirstName = firstName;
}
This works fine for a single property. It doesn't work for multiple, different properties because ViewModelB has no idea what property has changed on ViewModelA . ViewModelB knows what the new value is, but it doesn't know which of its properties to update.
I could create separate Events for each property but this seems repetitive. It seems cleaner to just use one Event. Ideally, when publishing the Event, ViewModelA should tell ViewModelB which property has changed. How can I do this?
Sorry, I found the answer to my question in this post. This blog post by Rachel Lim is also helpful.
What we need is for ViewModelA (the publisher) to tell ViewModelB (the subscriber) two pieces of information:
What property has changed on ViewModelA
What is the new value of this property
We need to communicate 2 pieces of information (i.e. properties) but Prism's EventAggregator takes only one parameter, the payload. This is the problem.
To pass multiple pieces of information (properties) via the EventAggregator you can publish an instance of a class which defines these properties as the EventAggregator's payload. I called this class PatientDetailsEventParameters and it defines two properties:
public class PatientDetailsEventParameters
{
public string PatientProperty { get; set; }
public string Value { get; set; }
}
I created this class in an Infrastructure assembly (the same place where I define my Events) which all my other assemblies have a reference to.
You can then publish an instance of this class as the payload (instead of a string which holds only 1 value). This allows for multiple parameters to be passed into the payload.
public string FirstName
{
get
{
return firstName;
}
set
{
this.firstName = value;
eventAggregator.GetEvent<PatientDetailsEvent>().Publish(new PatientDetailsEventParameters() {Value = firstName, PatientProperty = "firstName"});
}
}
You can see here that a new instance of my PatientDetailsEventParameters is created when the PatientDetailsEvent is published. The two properties Value and PatientProperty are also set. PatientProperty is a string which tells ViewModelB (i.e. the subscriber) what property has changed. Value is the new value of the property that has changed.

MVVM - RaisePropertyChanged turning code into a mess

New to MVVM so please excuse my ignorance.
I THINK i'm using it right but I find my ViewModel has too many of these:
RaisePropertyChanged("SomeProperty")
Every time I set a property I have to raise that damned property changed.
I miss the days where I could just go:
public int SomeInteger { get; private set;}
These days I have to stick the "RaisePropertyChanged" in everywhere or my UI does not reflect the changes :(
Am I doing it wrong or are other people getting annoyed with the excessive number of magic strings and old school property setters?
Should I be using dependency properties instead? (I doubt that would help the code bloat anyway)
Despite these problems I still think MVVM is the way to go so I guess that's something.
Take a look at this What is the best or most interesting use of Extension Methods you've seen?.
It describes an extension method and a helper method that my Model and ViewModel classes use to enable the following strongly typed (no magic string) properties.
private string _name;
public string Name
{
get { return _name; }
set { this.NotifySetProperty(ref _name, value, () => this.Name); }
}
This is about as simple as I think it can get. Hope it helps.
You could use PostSharp's NotifyPropertyChanged attribute. Then all you have to do is to put an attribute on the class and that's it. E.g.:
[NotifyPropertyChanged]
public class MyClass
{
public string MyProperty { get; set; }
}
It helps to look at things from a different perspective: those are not complicated .NET properties, but simplified dependency properties.
Bindable properties of a view model in WPF are not identical to .NET properties, instead it is a kind of key-value store. If you want light-weight alternative to DependencyObject, you have an ability to implement this key-value store just buy calling certain function in setters - not bad, actually. Far from ideal too, of course, but your point of view is certainly unfair.
It does not get you back to the clean code, but I use a simple extension method to get the property name to avoid problems with magic strings. It also maintains the readability of the code, i.e. it is explicit what is happening.
The extension method is simply as follows:
public static string GetPropertyName(this MethodBase methodBase)
{
return methodBase.Name.Substring(4);
}
With this it means that you property sets are resilient against name changes and look like the following:
private string _name;
public string Name
{
get { return _name; }
set
{
name = value;
RaisePropertyChanged(MethodBase.GetCurrentMethod().GetPropertyName());
}
}
I've written more about this extension method here and I've published a matching code snippet here.
This will help:
"Kind Of Magic"
Effortless INotifyPropertyChanged
[http://visualstudiogallery.msdn.microsoft.com/d5cd6aa1-57a5-4aaa-a2be-969c6db7f88a][1]
as an example for adding it to one property:
[Magic]
public string Name { get { return _name; } set { _name = value; } }
string _name;
Another example for adding it to all the class properties:
[Magic]
public class MyViewModel: INotifyPropertyChanged
{
public string Name { get; set; }
public string LastName { get; set; }
.....
}

Resources