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

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>();
}
}

Related

aspnetboilerplate EventCloud example - design pattern

in this tutorial about the EventCloud example app:
https://aspnetboilerplate.com/Pages/Documents/Articles/Developing-MultiTenant-SaaS-ASP.NET-CORE-Angular/index.html
the text states: the creation of a new entity must be done using the static method "Create" in the "Event" class (not using "new Entity(....)")
1) so my first question is: which design pattern is this? Factory? Builder? other?
[Table("AppEvents")]
public class Event : FullAuditedEntity<Guid>, IMustHaveTenant
{
......
....
...
/// <summary>
/// We don't make constructor public and forcing to create events using <see cref="Create"/> method.
/// But constructor can not be private since it's used by EntityFramework.
/// Thats why we did it protected.
/// </summary>
protected Event()
{
}
public static Event Create(int tenantId, string title, DateTime date, string description = null, int maxRegistrationCount = 0)
{
var #event = new Event
{
Id = Guid.NewGuid(),
TenantId = tenantId,
Title = title,
Description = description,
MaxRegistrationCount = maxRegistrationCount
};
#event.SetDate(date);
#event.Registrations = new Collection<EventRegistration>();
return #event;
}
....
...
2) the second question:
than the article says...
Event Manager .... All Event operations should be executed using this class... (EventManager)
ok, the CreateAsync method call the repository insert method, is the static "Event.Create" internaly called from the repository insert method? if yes, could you indicate me the point in the abp source code?
or is it an internal matter of EntityFramework?
public class EventManager : IEventManager
{
......
....
..
public async Task CreateAsync(Event #event)
{
await _eventRepository.InsertAsync(#event);
}
Here are my answers:
1-) Event is being created with a static factory method. There are 2 ways to create an entity in Domain Driven Design.
Creating with static factory methods: It's a convenient way of creating business entities. And this method is being used in EventCloud. The only downside of this method is it's static! If your entity is holding state it's not good for testability. But there are 3 advantages of this approach;
They have names: for example Event.CreatePublicEvent(), Create.PrivateEvent()
They can cache: You can cache them in a private static HashSet or Dictionary.
They can subtype.
Creating with a constructor: If you have only one constructor then creating an object through its public constructor is the most convenient approach in Domain Driven Design. As long as you make parameterless constructor protected or private. Besides, an entity should be responsible for its own data integrity and validity so you have to set all business related public properties as private setter and you should allow them to change through public methods.
Further information, see https://www.yegor256.com/2017/11/14/static-factory-methods.html
2-) EventManager is a domain service that is used for business logic. And Event.Create() is being used in the EventAppService class. Click here to see where exactly is being executed. Even Event.Create() method consists of a single line of code but it's open for extension.
I hope that will be useful ;)
Happy coding...

wicket :how to combine CompoundPropertyModel and LoadableDetachableModel

I want to achieve two goals:
I want my model to be loaded every time from the DB when it's in a life-cycle (for every request there will be just one request to the DB)
I want my model to be attached dynamically to the page and that wicket will do all this oreable binding for me
In order to achieve these two goals I came to a conclusion that I need to use both CompoundPropertyModel and LoadableDetachableModel.
Does anyone know if this is a good approach?
Should I do new CompoundPropertyModel(myLoadableDetachableModel)?
Yes, you are right, it is possible to use
new CompoundPropertyModel<T>(new LoadableDetachableModel<T> { ... })
or use static creation (it does the same):
CompoundPropertyModel.of(new LoadableDetachableModel<T> { ... })
that has both features of compound model and lazy detachable model. Also detaching works correctly, when it CompoudPropertyModel is detached it also proxies detaching to inner model that is used as the model object in this case.
I use it in many cases and it works fine.
EXPLANATION:
See how looks CompoundPropertyModel class (I'm speaking about Wicket 1.6 right now):
public class CompoundPropertyModel<T> extends ChainingModel<T>
This mean, CompoundPropertyModel adds the property expression behavior to the ChainingModel.
ChainingModel has the following field 'target' and the constructor to set it.
private Object target;
public ChainingModel(final Object modelObject)
{
...
target = modelObject;
}
This take the 'target' reference to tho object or model.
When you call getObject() it checks the target and proxies the functionality if the target is a subclass of IModel:
public T getObject()
{
if (target instanceof IModel)
{
return ((IModel<T>)target).getObject();
}
return (T)target;
}
The similar functionality is implemented for setObject(T), that also sets the target or proxies it if the target is a subclass of IModel
public void setObject(T object)
{
if (target instanceof IModel)
{
((IModel<T>)target).setObject(object);
}
else
{
target = object;
}
}
The same way is used to detach object, however it check if the target (model object) is detachable, in other words if the target is a subclass if IDetachable, that any of IModel really is.
public void detach()
{
// Detach nested object if it's a detachable
if (target instanceof IDetachable)
{
((IDetachable)target).detach();
}
}

Entity Framework - Automatically Adding Unattached Items

I use EF 5 and Code First.
Ive got a main ViewModel that exposes a Translation Property. A Translation consists out of 1 to n Translation Items. The Translation Property is bound to a Usercontrol. When the Translation is created and Added via _context.Translations.Add(t) in the Viewmodel also all TranslationItems inside the Translation are saved and stored correctly in the DB.
But when i try to Add a new TranslationItem (t.TranslationItems.Add) to a existing Translation it isn't saved in the DB. context.ObjectStateManager.GetObjectStateEntries(EntityState.Added) also returns no elements so i guess the new Translation Items is still unattached. Since the TranslationItem is added inside the Child Usercontrol, i can't access the current Datacontext To set the Entity State to Added.
What can i do?
Edit:
public class Translation : BaseEntity, IValidatableObject
{
private List<TranslationItem> _translations;
public virtual List<TranslationItem> Translations
{
get{
return _translations;
}
set
{
_translations = value;
}
}s
In ViewModel:
Translation = new Translation(); or
Translation = repo.GetTranslation(1);
Binding to custom Usercontrol:
<Views:TranslationTextInput Translations="{Binding Translation}"/>
In code behind of UserControl:
Trans.Translations.Add(new TranslationItem() { Text = "", Lcid = new CultureInfo("en").LCID });
Save function:
public void Update(Translation t)
{
if (t.Id == 0)
_context.Units.Add(t);
_context.SaveChanges();
}
I create the Context in the Viewmodel Constructor and pass it to the repository class.
The ChangeTracker should automatically grab all it's children if the Translation is properly attached. However, you could try attaching all of the TranslationItems inside the Translation if you're sure that the Translation is attached to the context.
I'm not sure of the DbSet name for TranslationItems, change that to whatever you named it.
public void Update(Translation t)
{
if (t.Id == 0)
_context.Units.Add(t);
foreach (var ti in t.Translations)
{
if (_context.Entry(ti).State == EntityState.Detached)
{
_context.TranslationItems.Attach(ti);
}
}
_context.SaveChanges();
}

WPF, C# and MVVM Exposing commands

Hi all I'm trying to get to grips with using MVVM, but I'm having a hard time :(, firstly for my question, I'm using the code provide in this MVVM article as a template for my learning.
My question is simple how do expose independent commands, in this case he has create a list of hyperlinks, but how do i create a single button that's fixed and does the same as the 'create new customer' link.
I created something like this(was added to the MainWindowViewModel.cs):
public CommandViewModel exposedCommand
{
get
{
return new CommandViewModel(
Strings.MainWindowViewModel_Command_CreateNewCustomer,
new RelayCommand(param => this.CreateNewCustomer())
);
}
}
and then in the xaml document i created a new button, this was added to the MainWindow.xaml
<Button
Content="Button"
Height="23"
HorizontalAlignment="Left"
Margin="6,303,0,0" Name="button1" VerticalAlignment="Top" Width="150"
Command="{Binding Path=exposedCommand}"
/>
I am not to sure if I'm missing something, or what I am where going wrong,
Soz if I sounding a bit naive I have only just started using MVVM and routed commands and so.
Oh another thing it does load the link it just doesn't create the tab, in other words if you would to add
Console.Writeline("HERE");
to the exposedCommand method
It would print out 'HERE' it just won't do anything when you click the button.
Thanks Any Help would be so appreciated.
Your XAML code is correct.
I also started off with Josh Smith's MVVM article.
Below is a stripped down example of how I implement Commands in my ViewModels:
public class ProjectViewModel : ViewModelBase
{
// Private variable for holding save command
private RelayCommand _saveCommand;
// Other fields here
// Constructors and properties and stuff here
// Command Property for Save button. Bind XAML to "SaveCommand"
public ICommand SaveCommand
{
get
{
if (_saveCommand == null) // Init command on first get
_saveCommand = new RelayCommand(param => this.SaveChanges(), param => this.CanSave);
return _saveCommand;
}
}
/// <summary>
/// Method called when save command is executed
/// </summary>
private void SaveChanges()
{
// Save logic here...
}
/// <summary>
/// Predicate for determining if SaveCommand is enabled
/// </summary>
private bool CanSave
{
get
{
return true; // Replace with SaveCommand predicate logic
}
}
}
If it still does not work, check you runtime output for BindingErrors. If there is a BindingError that implies that the View cannot find the SaveCommand, then your ViewModel is not correctly set to be the DataContext of the View. Let me know in the comments if this is the problem.
You can bind command to only those objects that has an implementation of ICommand interface.
In your example you are binding with view model object.
Instead of this create a property in view model that is a type of RelayCommand and bind this with button.
It should work.
The first thing that concerns me is your the code inside the getter of you property. You're returning a new object EVERY TIME the exposedCommand is accessed. That's not really recommended, you should store that in a backing property like so:
CommandViewModel _exposedCommand;
public CommandViewModel exposedCommand
{
get
{
if (_exposedCommand == null)
{
_exposedCommand = new CommandViewModel(
Strings.MainWindowViewModel_Command_CreateNewCustomer,
new RelayCommand(param => this.CreateNewCustomer()));
}
return _exposedCommand;
}
}
That being said the typical way to present your desired ICommand property is something like this:
RelayCommand _exposedCommand;
public ICommand exposedCommand
{
get
{
if (_exposedCommand == null)
_exposedCommand= new RelayCommand(param => this.CreateNewCustomer());
return _exposedCommand;
}
}

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.