Converting values (kg to lbs) in MVVM pattern - mvvm

I am building an app that can track weight. I allow the user to select their unit preference of kg or lbs. I want to keep the data in the DB standard (kg) so if the user selects lbs as their preference I need the data converted from kg to lbs in the UI.

This conversion can be handled very easily in the ViewModel.
This is one of the huge advantages of having a ViewModel - you can have easily testable logic, such as conversion between units, which stays completely separate from the user interface code.

I suggest you to use it Coverter Property of DataBinding and resolve it by XAML.
DataBinding = { Binding Path = YourProperty,Converter = {StaticResource YourConverter}}
YourConverter must implement the IValueConverter inferface (msdn doc) and has to be declare as Resource.
I would prefer this approach because keep the conversion logic on the View Side.

I'm supposing we are in WPF. Use a Binding Converter and create an object implementing IValueConverter doing the proper configured conversion.

The best way I can explain to do this is to use a custom converter interface. Instead of talking on I'll just zap you an example.
private IConverter<Double, Double> weightConverter = new KgToLbsConverter();
private double _weight;
public double Weight
{
get
{
return weightConverter.ConvertFrom(_weight);
}
set
{
_weight = weightConverter.ConvertTo(value);
RaisePropertyChanged(() => Weight);
}
}
/// <summary>
/// Provides a simple converter contract.
/// </summary>
/// <typeparam name="T">The source Type</typeparam>
/// <typeparam name="R">The target Type.</typeparam>
public interface IConverter<T, R>
{
R ConvertFrom(T value);
T ConvertTo(R value);
}
/// <summary>
/// Provides a converter to change Kg to Lbs and vice versa
/// </summary>
public class KgToLbsConverter : IConverter<Double, Double>
{
/// <summary>
/// From Kg to Lbs.
/// </summary>
/// <param name="value">The weight in Kg.</param>
/// <returns>The weight in Lbs.</returns>
public double ConvertFrom(double value)
{
return value / 2.2;
}
/// <summary>
/// From Lbs to Kg.
/// </summary>
/// <param name="value">The weight in Lbs.</param>
/// <returns>The weight in Kg.</returns>
public double ConvertTo(double value)
{
return value * 2.2;
}
}
Using this you could make can any converters you want, and then let the user select from concrete implementations.
Note: The reason I prefer this over converters is view models may need to know what conversion mode is active and how to work with them, this adds quite a bit of flexibility. When you need a single conversion for a V-VM relationship then IValueConverter is the way to go, but for your scenario, this is easier to maintain and to extend.

Related

How to call GL.IssuePlugInEvent in Unity3d and pass parameters to the plugin side in C

I'm trying to write a plugin for Unity that passes information between the native side of android (but same may apply to any other dll or so library) and the unity side. The information I want to share is OpenGL related. On Unity docs it's specified that everything that has to run on the rendering thread must be called through The GL.IssuePlugInEvent function. This function though is quite strict on the parameters: it needs a to call a function with a specific signature:
Callback must be a native function of "void UNITY_INTERFACE_API UnityRenderingEvent(int eventId)" signature
and has only the additional parameter eventId.
How can I then pass back on the unity side information from the so library?
The Unity examples for creating a plugin and using IssuePluginEvent cover the case where you want/need to call directly a C function, and this function accepts only an eventId as parameter. If the reader comes from a C\C++ background and is not familiar with C#, it may be misleading. In fact, you can actually call a C# function with this simple trick, and inside that function call your C functions passing multiple parameters.
The steps are:
get a function pointer for a C# function (notice that the function will be static)
pass that function pointer to GL.IssuePluginEvent
inside your static C# function, based on the case of eventId, call the appropriate C function
void Update()
{
GL.IssuePluginEvent(RenderThreadHandlePtr, GL_INIT_EVENT); // example
}
/// <summary> Renders the event delegate described by eventID. </summary>
/// <param name="eventID"> Identifier for the event.</param>
private delegate void RenderEventDelegate(int eventID);
/// <summary> Handle of the render thread. </summary>
private static RenderEventDelegate RenderThreadHandle = new RenderEventDelegate(RunOnRenderThread);
/// <summary> The render thread handle pointer. </summary>
public static IntPtr RenderThreadHandlePtr = Marshal.GetFunctionPointerForDelegate(RenderThreadHandle);
public const int GL_INIT_EVENT = 0x0001;
public const int GL_DRAW_EVENT = 0x0002;
/// <summary> Executes the 'on render thread' operation. </summary>
/// <param name="eventID"> Identifier for the event.</param>
[MonoPInvokeCallback(typeof(RenderEventDelegate))]
private static void RunOnRenderThread(int eventID)
{
switch (eventID)
{
case GL_INIT_EVENT:
glInit(par1, par2, par3); // C function with 3 parameters
break;
case GL_DRAW_EVENT:
glStep();
GL.InvalidateState();
break;
}
}
[DllImport("hello-jni")]
private static extern void glInit(int par1, int par2, int par3);
[DllImport("hello-jni")]
private static extern void glStep();

Relization of XElement, XAttribute + IDataErrorInfo for binding in wpf app

I use mvvm pattern in wpf app. As datasource i've XDocument. In UI i bind controls to XElements and XAttribute's values from this XDocument.
f.ex.
<TextBox Text={Binding XElement[TitleNode].XElement[Title].Value} />
It allows me to have data in only place - in XDoc and allows to avoid data conversion from custom models to xml.
Now I need to extend functionality of model with IDataErrorInfo to realize error notification. So i need to add interface to XElement and XAttribute .net classes.
i've 2 decisions:
1) pattern adapter for xelement and xattribute, that will have adaptee, realiztion of interface IDataErrorInfo and Value setter\getter for xelement\xattribute's value. Weakness - i need create adapter-objects for all UI input control and bind to it.
2) Create child class and inherite from XElement\XAttribute with interface realization. Weekness - i need to convert all xelements and xattributes to my child class.
What way is better?
The best way I guess is to inherite from XElement/XAttribute and add interface you need.
I created 2 child class XElementCustom and XAttributeCustom. And in constructor the whole tree is recreated recursively
That's my realization:
/// <summary>
/// Наследник XML с реализацией INotifyPropertyChanged
/// </summary>
public class XElementCustom : XElement, INotifyPropertyChanged, IDataErrorInfo, IDataErrorInfoValidating
{
public XElementCustom(XElement sourceElement)
:base(sourceElement.Name.LocalName)
{
if (sourceElement.Elements().Any())
{
foreach (var element in sourceElement.Elements())
{
this.Add(new XElementCustom(element));
}
}
else
{
this.Value = sourceElement.Value;
}
foreach (var attribute in sourceElement.Attributes())
{
this.Add(new XAttributeCustom(attribute));
}
_changedProperties = new List<string>();
}
}

Breeze JS - Repository with EFContextProvider, enabling/disabling OData filtering

I'm looking to implement a repository pattern with breeze EFContextProvider. In this repository, I would expose a method to query the DB using OData filtering... just as breeze behaves by default. I would also want to expose a method that would ignore OData filtering, and return a list of elements as if it was the default EF Context.
So, to sum up, my idea would be to try to do something like this:
public class RepositoryBaseEntity<T> : IRepository<T> where T : class
{
protected Breeze.WebApi.DataModelContainer _context;
public RepositoryBaseEntity(Breeze.WebApi.EFContextProvider<DataModelContainer> context)
{
_context = context;
}
/// <summary>
/// Gets all elements, ignoring OData filtering
/// </summary>
/// <returns>All elements, or null if none exists</returns>
public IEnumerable<T> GetAll()
{
// disable OData filtering in Breeze.WebApi.EFContextProvider
return _context.Context.Set<T>();
}
/// <summary>
/// Apply ODataFilters and get elements. Useful for Web API controllers
/// </summary>
/// <returns></returns>
public IEnumerable<T> ApplyODataFiltersAndGet()
{
// enable OData filtering in Breeze.WebApi.EFContextProvider
return _context.Context.Set<T>();
}
}
I've been taking a look at Breeze EFContextProvider, and there doesn't seem to be a way of disabling OData filtering.
I've though about maybe using the plain old Entity Framework DataModelContainer when I don't want OData filtering, and using Breeze EFContextProvider wrapper when I do want OData filtering... but using this approach I would have two EF contexts... and that's something i want to avoid... in the past in some other projects we've had some problems using more than one EF contexts.
So, you guys see any way of doing this? Thanks!
The OData filtering is actually applied by WebApi prior to executing and JSON-serializing the result. The EFContextProvider provides the initial query, but it does not apply the OData filter because it doesn't know anything about OData.
To control the filtering in WebApi, add an ODataQueryOptions parameter to your WebApi controller methods. This prevents WebApi from applying the filtering, and allows you to do it instead:
public IEnumerable<Customer> Customers(ODataQueryOptions options)
{
if (youWantToApplyFilters)
{
return repository.ApplyODataFiltersAndGet(options);
}
else
{
return repository.GetAll();
}
}
Then, in your repository,
/// <summary>
/// Apply ODataFilters and get elements. Useful for Web API controllers
/// </summary>
/// <returns></returns>
public IEnumerable<T> ApplyODataFiltersAndGet(ODataQueryOptions options)
{
var set = _context.Context.Set<T>();
return options.ApplyTo(set).Cast<T>();
}
Note that ODataQueryOptions is in System.Web.Http.OData.Query, which means that your repository would be WebApi-specific. If you don't like that, you can move the filtering out of the repository and closer to the controller, or you can pull apart the ODataQueryOptions and put the filtering parameters in your own object (but then you'd have to apply them to the query yourself).

Publish an Event without PayLoad in Prism EventAggregator?

Why can't we Publish Events without any PayLoad.
_eventAggregator.GetEvent<SelectFolderEvent>().Publish(new SelectFolderEventCriteria() { });
Now, I don't need any pay load to be passed here. But the EventAggregator implementation mandates me to have an empty class to do that.
Event:
public class SelectFolderEvent : CompositePresentationEvent<SelectFolderEventCriteria>
{
}
PayLoad:
public class SelectFolderEventCriteria
{
}
Why has Prism not given a way to use just the Event and publish it like
_eventAggregator.GetEvent<SelectFolderEvent>().Publish();
Is it by design and I don't understand it?
Please explain. Thanks!
Good question, I don't see a reason for not publishing an event without a payload. There are cases where the fact that an event has been raised is all information you need and want to handle.
There are two options: As it is open source, you can take the Prism source and extract a CompositePresentation event that doesn't take a payload.
I wouldn't do that, but handle Prism as a 3rd party library and leave it as it is. It is good practice to write a Facade for a 3rd party library to fit it into your project, in this case for CompositePresentationEvent. This could look something like this:
public class EmptyPresentationEvent : EventBase
{
/// <summary>
/// Event which facade is for
/// </summary>
private readonly CompositePresentationEvent<object> _innerEvent;
/// <summary>
/// Dictionary which maps parameterless actions to wrapped
/// actions which take the ignored parameter
/// </summary>
private readonly Dictionary<Action, Action<object>> _subscriberActions;
public EmptyPresentationEvent()
{
_innerEvent = new CompositePresentationEvent<object>();
_subscriberActions = new Dictionary<Action, Action<object>>();
}
public void Publish()
{
_innerEvent.Publish(null);
}
public void Subscribe(Action action)
{
Action<object> wrappedAction = o => action();
_subscriberActions.Add(action, wrappedAction);
_innerEvent.Subscribe(wrappedAction);
}
public void Unsubscribe(Action action)
{
if (!_subscriberActions.ContainsKey(action)) return;
var wrappedActionToUnsubscribe = _subscriberActions[action];
_innerEvent.Unsubscribe(wrappedActionToUnsubscribe);
_subscriberActions.Remove(action);
}
}
If anything is unclear, please ask.
Just to update the situation since this question was asked/answered, as of Prism 6.2, empty payloads are now supported in Prism PubSubEvents.
If you're using an older version, this blog shows how to create an "Empty" class that clearly indicates the intent of the payload: https://blog.davidpadbury.com/2010/01/01/empty-type-parameters/

Silverlight MVVM header detail

So lets say i have an OrderModel and an OrderViewModel. I have the Supplier, Order Date, etc properties on both the ViewModel and the Model and they are linked up. Seen examples on this and seems straighforward enough, although somewhat duplicated in terms of writing setters/getters.
Now what do I do with the OrderDetails? In my model I would have a List.
Do I have an OrderDetailViewModel for the OrderDetail? If so then how does the OrderViewModel provide that? As an ObservableCollection? And if so how do you keep that in sync with the original List?
This is where I haven't seen a decent example. If there is one out there someone could point me to, I'd appreciate it. I liek the concept of the MVVM but I am starting to thing its a hell of a lot of overhead. Why not just have the ViewModel handle the model part as well. In day to day LOB apps is there really that much difference between the two to warrant all the code that true MVVM seems to required?
It looks like this is what you need: http://jonas.follesoe.no/SpeakingAtMSDNLiveNextMonth.aspx
A translation on google gives this as the abstract for the talk:
Silverlight 2 was released this autumn, and lays a good foundation for developers who want to create rich Internet applications (RIA) based on. NET. In this session we in Depth in Silverlight 2 that development and the benefits of choosing Silverlight 2 as a platform for data-centric business applications. The session will cover among other things, data access via secured WCF services, how to structure the code using the Model-View-View Model pattern (MVVM), how to write code, designers can work with, and easy-Blend tips for developers. The session will be built around a dive log application where the code will be available after the presentation.
However in the mean time Jonas has already talked about MVVM here:
http://jonas.follesoe.no/YouCardRevisitedImplementingTheViewModelPattern.aspx
You can use something like this to keep your ObservableCollections synchronised between the model and view model:
/// <summary>
/// Keeps one collection synchronised with another.
/// </summary>
/// <typeparam name="Source">The type of the source items.</typeparam>
/// <typeparam name="Destination">The type of the destination items.</typeparam>
public class CollectionSync<Source, Destination>
{
private readonly Func<Source, Destination> _destItemFactory;
private readonly Action<Destination> _destItemRemover;
private readonly IList<Destination> _destList;
private readonly IList<Source> _sourceList;
/// <summary>
/// Initializes a new instance of the <see cref="CollectionSync<Source, Destination>"/> class.
/// </summary>
/// <param name="sourceList">The source list.</param>
/// <param name="destList">The destination list.</param>
/// <param name="destItemFactory">Factory method which creates a Destination for a given Source.</param>
/// <param name="destItemRemover">Method called when a Destination is removed.</param>
public CollectionSync(IList<Source> sourceList,
IList<Destination> destList,
Func<Source, Destination> destItemFactory,
Action<Destination> destItemRemover)
{
_destItemFactory = destItemFactory;
_destItemRemover = destItemRemover;
_sourceList = sourceList;
_destList = destList;
((INotifyCollectionChanged) _sourceList).CollectionChanged += SourceCollection_CollectionChanged;
PopulateWithAllItems();
}
private void PopulateWithAllItems()
{
foreach (Source sourceItem in _sourceList)
_destList.Add(_destItemFactory(sourceItem));
}
private void SourceCollection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs args)
{
switch (args.Action)
{
case NotifyCollectionChangedAction.Add:
OnItemsAdded(args.NewStartingIndex, args.NewItems);
break;
case NotifyCollectionChangedAction.Remove:
OnItemsRemoved(args.OldStartingIndex, args.OldItems);
break;
case NotifyCollectionChangedAction.Reset:
OnItemsReset();
break;
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
throw new NotImplementedException();
}
}
private void OnItemsReset()
{
_destList.Clear();
PopulateWithAllItems();
}
private void OnItemsRemoved(int index, ICollection items)
{
int itemCount = items.Count;
for (int i = 0; i < itemCount; i++)
{
Destination removed = _destList[index];
_destList.RemoveAt(index);
if (_destItemRemover != null)
_destItemRemover(removed);
}
}
private void OnItemsAdded(int index, IList items)
{
int itemIndex = index;
foreach (Source item in items)
{
// Add to Items collection
_destList.Insert(itemIndex, _destItemFactory(item));
itemIndex++;
}
}
}
Taking your Order/OrderDetails example, in your Order view model you would hook up the two ObservableCollections like this:
_modelToViewModelSync = new CollectionSync<IOrderDetail, OrderDetailViewModel>(
orderDetailModels, // the list of your order details models
OrderDetails, // the list of order details view models exposed by the Order view model
x => new OrderDetailViewModel(x), // factory method to create a view model
null); // do something here if you care when your view models are removed
When it comes to the question "Do I need another view model", my answer is this: If all your view is doing is showing the model data, there is no harm in binding directly to the order directly. Creating a ViewModel for this would be very much redundant. The time when the ViewModel needs to be created is when you have logic or state in the "order detail" screen that needs to be represented. Instead of adding that to the model, you create a ViewModel at that time.
As far as keeping those items in sync, Similar to GraemeF, I have created a Binder class that is uses reflection to bind two values together. It keeps my model and viewmodel properties in sync, and it can be used to keep other things in sync, like this particular collection. There is some overhead in creating a binder like this, but once it is done, you can specify data correlations in a functional way, which is really nice.