Updating another property based on a property, vice versa - wpf

My issue is I have three properties with mutually dependent in my WPF application. I have implemented InotifyPropertyChanged also for the class. I am not sure how to update second property based on other.
Example:
Properties : ActualValue, ChangedValue, Change
ActualValue is Fixed, and it is possible to update ChangedValue and Change. That means if I update ChangedValue, the Change is calculated like (ActualValue-ChangedValue) and set. And when Change updates, the ChangedValue will be calculated based on ActualValue and Change.

You can put the logic inside the setters of properties that others depend on. Since it's a circular dependency, just make sure that inside the setters you change the private variable-- don't use the property setter, as that would create an infinite loop. Like this:
private string _change, _changedValue;
public string ChangedValue {
set {
_changedValue = value;
_change = ActualValue - _changedValue;
NotifyPropertyChanged("ChangedValue");
NotifyPropertyChanged("Change");
}
}
public string Change {
set {
_change = value;
_changedValue = ActualValue - _change;
NotifyPropertyChanged("Change");
NotifyPropertyChanged("ChangedValue");
}
}

Related

Is a Value changed through Input?

How do I know when is a value of any control changed by user input (interaction with mouse or keyboard)?
Any suggestions? Is there a common way for this?
EDIT:
I am seeking for attached property or extending already given controls or whatever is needed just to get notified whether user input is taking place at the time value is changed. eg ComboBox SelectedItem changed by user input (User could enter text or select an item in drop down menu)
Its pure View thing therefore I am sorry but no ViewModel solutions for this issue will be accepted.
The simplest way would simply be to register to the Binding.TargetUpdated event, which is fired when the UI-side is updated (while Binding.SourceUpdated is fired when the ViewModel-side is updated)
Use a property with backing field in your view model. Introduce a second setter - a SetProp() method - that you use inside your ViewModel. That way you can add different behavior, depending on the origin of the call.
```
private bool mMyProp;
public bool MyProp
{
get { return mMyProp; }
set
{
if (mMyProp != value)
{
mMyProp = value;
// Todo: add here code specific for calls coming from the UI
RaisePropertyChanged(() => MyProp);
}
}
}
public void SetPropFromViewModel(bool value)
{
if (mMyProp != value)
{
mMyProp = value;
// Todo: add here code specific for calls coming from ViewModel
RaisePropertyChanged(() => MyProp);
}
}

Update a wpf label periodically

I am new to WPF and C# im trying to understand how can I update a UI element from a BL class (to keep a seperation between the logic and the UI) the bl gets periodic updates from a c++ network component and should update the form once a new argument comes in (I read on the msdn website but I want to see some concrete examples to make sure I got it right)
Because of your gets periodic updates from a c++ network component comment, I am assuming that you already have a system to update your property. I would expose that property from your business class in a view model class, a class with public properties and ICommand functions designed specifically to supply all of the required data to a view, or UserControl.
To be honest, I wouldn't have that (or any) functionality in a business class (depending what you mean by business class)... I'd personally put it straight into the view model, or have a manager/service class that exposed it.
If you insist on keeping it where it is, you'll have to implement either an event or a delegate in your business class so that users of that class can be alerted as to when the value changes. Then you could simply attach a handler to your event/delegate from the view model class and easily update the exposed property whenever the actual property changes.
So it would go a little something like this... in your business class (I am assuming that your value is an int, but you can change this if it is incorrect... the principal is the same):
public delegate void FieldUpdate(int value);
public FieldUpdate OnFieldUpdate { get; set; }
...
private int field;
public int Field
{
get { return field; }
set
{
if (value != field)
{
field = value;
if (OnFieldUpdate != null) OnFieldUpdate(field);
}
}
}
Then in your view model:
private YourBusinessClass instance = new YourBusinessClass();
public YourBusinessClass Instance
{
get { return instance; }
set { instance = value; NotifyPropertyChanged("Instance"); }
}
Attach a handler:
instance.OnFieldUpdate += OnBusinessClassFieldUpdate;
...
public void OnBusinessClassFieldUpdate(int value)
{
Instance = value;
}
Now whenever the field is updated in the business class, the view model (and data bound UI controls) will automatically update via the delegate.

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.

EntityFramework EntityState and databinding along with INotifyPropertyChanged

I have a WPF view that displays a Shipment entity. I have a textblock that contains an asterisk which will alert a user that the record is changed but unsaved. I originally hoped to bind the visibility of this (with converter) to the Shipment.EntityState property.
If value = EntityState.Modified Then
Return Visibility.Visible
Else
Return Visibility.Collapsed
End If
The property gets updated just fine, but the view is ignorant of the change. What I need to know is, how can I get the UI to receive notification of the property change. If this cannot be done, is there a good way of writing my own IsDirty property that handles editing retractions (i.e. if I change the value of a property, then change it back to it's original it does not get counted as an edit, and state remains Unchanged).
Any help, as always, will be greatly appreciated.
Cory
After struggling with the same problem for a little bit, here is a solution that is working for me.
Lets say I have an entity called Trip that was generated by EF, I just needed to extend the class by means of partial class as showed below. The RaiseEntityStateChanged method is useful when you need to force a refresh of the EntytyState property, for example after calling the context's SaveChanges method.
partial class Trip
{
bool _forced = false;
System.Data.EntityState _lastState;
public Trip()
{
_lastState = EntityState;
this.PropertyChanged += (s, e) =>
{
if (_lastState != this.EntityState && e.PropertyName != "EntityState" || _forced)
{
_forced = false;
OnPropertyChanged("EntityState");
}
_lastState = this.EntityState;
};
}
public virtual void RaiseEntityStateChanged()
{
_forced = true;
OnPropertyChanged("EntityState");
}
}
I don't see a way to create a XAML binding on an existing property to do what you are trying to do. But you could write your own IsDirty property, based on the EntityState; you could update this value by subscribing to the PropertyChanged event raised by the base EntityObject. Of course, you'll need to also raise a PropertyChanged event for IsDirty (so that the GUI is notified) and ignore this event in your handler (to prevent infinite recursion).
Edit: added the following after question by OP:
This is how I see it, in order to answer the comment.
In the shipment class, one can add:
public bool IsDirty { get { return EntityState == EntityState.Modified; } }
public Shipment() {
...
PropertyChanged += OnShipmentChanged;
}
private void OnShipmentChanged(object sender, PropertyChangedEventArgs pcea) {
if (pcea.PropertyName != "IsDirty") { // prevent recursion
OnPropertyChanged("IsDirty"); // notifies binding listener that the state has changed
}
}
During the night, I thought of another way, which is to create a multi-binding on each Shipment property (which would replace this whole notion of an IsDirty property and would actually answer the original question). This could make sense if there are just a couple of Shipment properties. I'd say if there are more than 3, we should forget about this idea.

Value Object and View Model Property

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.

Resources