In WinRT, A Collection that implements INotifyCollectionChanged not Updating ItemsControl - windows-8

I am writing my own collection class that also implements INotifyCollectionChanged. I am using it in a windows 8 store application (winRT). I wrote a unit test that proves that modifying the content of the list raises all the proper events with the same events a "normal" observable collection would raise. Still, when I bind the ItemsSource property of an ItemsControl (I tried GridView, ListView, and even plain vanilla ItemsControl) to the collection, it does not affect the UI when the collection is changed.
Does the underlying collection type HAVE to be an ObservableCollection for it to work or is it possible to write my own collection class?
Thnx

You can use an ICollectionView that has some extended functionality for filtering as well. If you want a premade class, check out one available at Code Project.
In particular, I noticed that the UI subscribes to the VectorChanged event, so you should be good with only implementing IObservableCollection noted earlier in the comments.
The VectorChanged event takes an interface of type IVectorChangedEventArgs, and I found no concrete classes when looking around. It's not difficult to create one though. Here's one that can be created similar to how you create an instance of NotifyPropertyChangedEventArgs. It's private since it's only used in the collection class.
private sealed class VectorChangedEventArgs : IVectorChangedEventArgs
{
public VectorChangedEventArgs(NotifyCollectionChangedAction action, object item, int index)
{
switch (action)
{
case NotifyCollectionChangedAction.Add:
CollectionChange = CollectionChange.ItemInserted;
break;
case NotifyCollectionChangedAction.Remove:
CollectionChange = CollectionChange.ItemRemoved;
break;
case NotifyCollectionChangedAction.Move:
case NotifyCollectionChangedAction.Replace:
CollectionChange = CollectionChange.ItemChanged;
break;
case NotifyCollectionChangedAction.Reset:
CollectionChange = CollectionChange.Reset;
break;
default:
throw new ArgumentOutOfRangeException("action");
}
Index = (uint)index;
Item = item;
}
/// <summary>
/// Gets the affected item.
/// </summary>
public object Item { get; private set; }
/// <summary>
/// Gets the type of change that occurred in the vector.
/// </summary>
public CollectionChange CollectionChange { get; private set; }
/// <summary>
/// Gets the position where the change occurred in the vector.
/// </summary>
public uint Index { get; private set; }
}

Related

ObservationCollection that implements ISupportIncrementalLoading within ViewModel inside PCL using MVVM architecture for WinRT & WP8/WinPRT support

I have my ViewModels inside a PCL, because I'm developing a Windows 8.1 and Windows Phone app in parallel. I have a list of things inside my ViewModel as an ObservableCollection.
I have a GridView inside a Page inside a Windows 8.1 project. I wish to incrementally load items from my list of things in my ViewModel. Normally I would implement ISupportIncrementalLoading inside a custom subclass of ObservableCollection, however, given that my ViewModel is inside a PCL, ISupportIncrementalLoading is not available (it's not supported by WP8).
So my question is, does anyone have any suggestions as to how I can create some kind of converter, adapter or abstraction layer between the ItemsSource binding of the GridView and the Observable Things property of my ViewModel which would implement ISupportIncrementalLoading and then call the ViewModel's LoadMoreThings method and pass the items to the GridView.
I feel like there is some solution, such as creating a custom ISupportIncrementalLoading inside my View Models PCL and then have the View layer delegate to it.
thanks
In the end, I used the abstract factory pattern. The facts are:
You cannot reference the View layer from the PCL ViewModel layer, as the VM layer should not be concerned with the View layer. One of the benefits of this is that you can create another consumer of the ViewModel layer without any dependencies on the target platform. e.g. create a Windows 8 and Windows Phone 8 app off the back of one ViewModel library PCL project.
The GridView is a WinRT component which can bind to an ObservableCollection<T>. ObservableCollection<T> is available inside both the View layer and ViewModel layer. If you want to support incremental loading inside your app (which is a must for large datasets), then you need to create a special subclass of ObservableCollection<T> that implements ISupportIncrementalLoading. What we want to do is just create that subclass inside the ViewModel project and you're done. But we cannot do this because ISupportIncrementalLoading is only available inside a WinRT project.
This problem can be resolved by using the abstract factory pattern. All the ViewModel really wants is an ObservableCollection<T>, but the View layer demands an ObservableCollection that implements ISupportIncrementalLoading. So the answer is to define an interface in the ViewModel layer that gives the ViewModel exact what it wants; let's call it IPortabilityFactory. Then in the View layer define a concrete implementation of IPortabilityFactory called PortabilityFactory. Use an IoC in the View layer to map IPortabilityFactory (ViewModel interface) to PortabilityFactory (View layer concrete impl.).
On the constructor of the ViewModel class, have an IPortabilityFactory instance injected. Now the ViewModel has a factory that will give it an ObservableCollection<T> instance.
Now instead of calling new ObservableCollection<Thing>() in the ViewModel you call factory.GetIncrementalCollection<Thing>(...).
OK, so we're done with the ViewModel layer; now we need that custom implementation of the ObservableCollection<T>. It's called IncrementalLoadingCollection and it's defined in the View layer. It implements ISupportIncrementalLoading.
Here's the code and explanations, together with an implementation of ISupportIncrementalLoading.
In the ViewModel layer (PCL) I have an abstract factory interface.
public interface IPortabilityFactory
{
ObservableCollection<T> GetIncrementalCollection<T>(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> onBatchComplete);
}
In the View layer (Windows 8 app, in this case) I implement a concrete factory like this:
public class PortabilityFactory : IPortabilityFactory
{
public ObservableCollection<T> GetIncrementalCollection<T>(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> onBatchComplete)
{
return new IncrementalLoadingCollection<T>(take, loadMoreItems, onBatchStart, onBatchComplete);
}
}
Again, inside the View layer, I happen to use Unity for my IoC. When the IoC is created, I map IPortabilityFactory (in PCL) to PortabilityFactory (in View layer; the app project).
Container.RegisterType<IPortabilityFactory, PortabilityFactory>(new ContainerControlledLifetimeManager());
We now need to create a subclass of ObservableCollection and here's the code:
public class IncrementalLoadingCollection<T>
: ObservableCollection<T>, ISupportIncrementalLoading
{
private Func<int, Task<List<T>>> _loadMoreItems = null;
private Action<List<T>> _onBatchComplete = null;
private Action _onBatchStart = null;
/// <summary>
/// How many records to currently skip
/// </summary>
private int Skip { get; set; }
/// <summary>
/// The max number of items to get per batch
/// </summary>
private int Take { get; set; }
/// <summary>
/// The number of items in the last batch retrieved
/// </summary>
private int VirtualCount { get; set; }
/// <summary>
/// .ctor
/// </summary>
/// <param name="take">How many items to take per batch</param>
/// <param name="loadMoreItems">The load more items function</param>
public IncrementalLoadingCollection(int take, Func<int, Task<List<T>>> loadMoreItems, Action onBatchStart, Action<List<T>> onBatchComplete)
{
Take = take;
_loadMoreItems = loadMoreItems;
_onBatchStart = onBatchStart;
_onBatchComplete = onBatchComplete;
VirtualCount = take;
}
/// <summary>
/// Returns whether there are more items (if the current batch size is equal to the amount retrieved then YES)
/// </summary>
public bool HasMoreItems
{
get { return this.VirtualCount >= Take; }
}
public IAsyncOperation<LoadMoreItemsResult> LoadMoreItemsAsync(uint count)
{
CoreDispatcher dispatcher = Window.Current.Dispatcher;
_onBatchStart(); // This is the UI thread
return Task.Run<LoadMoreItemsResult>(
async () =>
{
var result = await _loadMoreItems(Skip);
this.VirtualCount = result.Count;
Skip += Take;
await dispatcher.RunAsync(
CoreDispatcherPriority.Normal,
() =>
{
foreach (T item in result) this.Add(item);
_onBatchComplete(result); // This is the UI thread
});
return new LoadMoreItemsResult() { Count = (uint)result.Count };
}).AsAsyncOperation<LoadMoreItemsResult>();
}
}
IncrementalLoadingCollection's constructor asks for four parameters which will be supplied by the ViewModel via the factory:
take - this is the page size
loadMoreItems - this is a delegate reference to a function inside the ViewModel that will retrieve the next batch of items (importantly, this function will not run inside the UI thread)
onBatchStart - this will be invoked just before the loadMoreItems method is called. This allows me to make changes to properties on the ViewModel that may impact the View. e.g., have an observable IsProcessing property which is bound to the Visibility property of a progress bar.
onBatchComplete - this will be invoked just after the retrieval of the latest batch and pass the items in. Crucially, this function will invoke on the UI thread.
In the ViewModel layer, my ViewModel has a constructor on it which accepts a IPortabilityFactory object:
public const string IsProcessingPropertyName = "IsProcessing";
private bool _isProcessing = false;
public bool IsProcessing
{
get
{
return _isProcessing;
}
set
{
if (_isProcessing == value)
{
return;
}
RaisePropertyChanging(IsProcessingPropertyName);
_isProcessing = value;
RaisePropertyChanged(IsProcessingPropertyName);
}
}
private IPortabilityFactory _factory = null;
public ViewModel(IPortabilityFactory factory)
{
_factory = factory;
Initialize();
}
private async void Initialize()
{
Things = _factory.GetIncrementalCollection<Thing>(10, LoadThings,
() => IsProcessing = true, BatchLoaded);
}
private void BatchLoaded(List<Thing> batch)
{
IsProcessing = false;
}
private async Task<List<Thing>> LoadThings(int skip)
{
var items = await _service.GetThings(skip, 10 /*page size*/);
return items;
}
I hope this helps someone.

Temporarily turn off identity column with Fluent AutoMap?

I have begun to test Fluent NHibernate in C#
I have a well normalized object structure with 20 related classes.
I currently use Fluent 1.3 with NHibernate 3.2.
So far I have managed to use the AutoMap feature which suits me fine,
Very convenient!
BUT ...
3 of the tables are "enum tables" that need to have their records set with specific Id value.
I tried to make manual mappings of these tables and let the rest be automapped.
But when the manual table is created it fails because it references a table that is automapped (and not available for manual mapper?)
Is it possible to use AutoMapping but for some very few classes override identity creation on primary key?
I tried to make a custom convention but without success.
public class OverrideIdentityGeneration : Attribute
{
}
public class ConventionIdentity : AttributePropertyConvention<OverrideIdentityGeneration>
{
protected override void Apply(OverrideIdentityGeneration attribute, IPropertyInstance instance)
{
instance.Generated.Never();
}
}
Is there some other way?
It would be sad to be forced back to use manual mapping for all classes ....
class MyIdConvention : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
if (instance.EntityType == ...)
{
instance.GeneratedBy.Assigned();
}
}
}
Update:
for enum-like classes it's often easier to define an enum as id
class ConfigValue
{
public virtual Config Id { get; set; }
}
// the convention is easy
if (instance.EntityType.IsEnum)
{
instance.GeneratedBy.Assigned();
// to save as int and not string
instance.CustomType(typeof(Config));
}
// querying without magic int values
var configValue = Session.Get<ConfigValue>(Config.UIColor);
I used the idea given by Fifo and extended it to use a custom attribute instead.
To make code readable and avoid redundance when using similar idea in other conventions I added an extension method to check for custom attribute.
This is the code I ended up with:
/// <summary>
/// Convention to instruct FluentNHIbernate to NOT generate identity columns
/// when custom attribute is set.
/// </summary>
public class ConventionIdentity : IIdConvention
{
public void Apply(IIdentityInstance instance)
{
if(instance.CustomAttributeIsSet<NoIdentity>())
instance.GeneratedBy.Assigned();
}
}
/// <summary>
/// Custom attribute definition.
/// </summary>
public class NoIdentity : Attribute
{
}
/// <summary>
/// Example on how to set attribute.
/// </summary>
public class Category
{
[NoIdentity]
public int Id { get; set; }
public string Name { get; set; }
}
public static class IInspectorExtender
{
/// <summary>
/// Extender to make convention usage easier.
/// </summary>
public static T GetCustomAttribute<T>(this IInspector instance)
{
var memberInfos = instance.EntityType.GetMember(instance.StringIdentifierForModel);
if(memberInfos.Length > 0)
{
var customAttributes = memberInfos[0].GetCustomAttributes(false);
return customAttributes.OfType<T>().FirstOrDefault();
}
return default(T);
}
}

WCF Data Service Partial class property on the client causes SaveContext exceptions

I have a WCF Data Service running that is exposing an EDM. There are several properties I needed on the client side, that the database doesn't need to know about. After setting all that up I got to testing the SaveContext method and get this error on the server "Error processing request stream. The property name 'CanDelete' specified for type 'DataModels.Customer' is not valid."
Is there a way to tell WCF Data Services on the client side to ignore this property? Or should I move to RIA Serivces? I've read that setting the property to internal will do this, but I need the property for binding and I have the client UI code in a different project (de-coupling my SL applications from my data service).
on the client I have:
public partial class Customer
{
private bool canDelete;
/// <summary>
/// Gets or sets a value indicating whether this instance can be deleted.
/// </summary>
/// <value>
/// <c>true</c> if this instance can delete; otherwise, <c>false</c>.
private bool canDelete;
/// <summary>
/// Gets or sets a value indicating whether this instance can be deleted.
/// </summary>
/// <value>
/// <c>true</c> if this instance can delete; otherwise, <c>false</c>.
/// </value>
public bool CanDelete
{
get
{
return this.canDelete;
}
set
{
if (this.canDelete != value)
{
this.canDelete = value;
this.OnPropertyChanged("CanDelete");
}
}
}
}
I had the exact same problem and adapted some code below from
extending partial designer classes
It simply involves hooking the WritingEntity Event inside a partial class of the Context.
I added my own attribute (IgnorePropertyAttribute) so I could attach it to other properties.
Would of course be nice if the attribute wasnt inserted in the first place but this worked for me
public sealed class IgnorePropertyAttribute : Attribute
{
}
...
partial void OnContextCreated()
{
this.WritingEntity += MyDataContext_WritingEntity;
}
private void MyDataContext_WritingEntity(object sender, System.Data.Services.Client.ReadingWritingEntityEventArgs e)
{
//
foreach (XElement node in e.Data.Elements())
{
if (node != null && node.Name.LocalName == "content")
{
foreach (XElement el in node.Elements())
{
if (el.Name.LocalName == "properties")
{
foreach (XElement prop in el.Elements())
{
if(e.Entity.GetType().GetProperty(prop.Name.LocalName).GetCustomAttributes(typeof(IgnorePropertyAttribute), true).Length > 0)
{
prop.Remove();
}
}
}
}
}
}
}

Designing an webtesting DSL to be implemented by different Web testing drivers - should we mix primitive and non-primitive operations?

We are implementing a web test automation project for some intranet applications.
To easy the writing of each test, we are designing a Java DSL that can be implemented using different adapters (we've chosen Sahi and Selenium/WebDriver so far, as we want to measure them side by side in terms of performance, readability, maintainability, etc.).
We've identified two types of operations in the DSL:
1) Primitive: its implementation will surely have to deal with HTML/Selenium/Sahi/etc specifics. Example: (using Sahi web driver)
public void insertProjectRecord(String projectName) {
b.link("Create new project").click();
b.textbox("ctl00$ProjectForm$Name").setValue(projectName);
b.span("Insert").click();
}
2) Non-Primitive: an operation worth including in our DSL for reusability purposes, although that can be built using primitives. Example:
public void createFormulation(String projectName, String rteDummyText) {
goToAddProjectPage();
insertProjectRecord(projectName);
switchToEditModeForFirstAvailableRecord();
editBeneficiaryCountries();
editAcronyms(rteDummyText);
saveSectionChanges();
}
Question: we initially started with an interface with only primitive operations, but later we changed it to an abstract class in order to include the non-primitive methods (which a specific implementations are allowed to override, if needed).
However, it doesn't feel "OK" to mix primitives and non-primitives, and the list of methods will certainly became very long.
What other approach would you suggest and/or explore?
I would highly recommend using the Page Object Model. In this you create a class for each page and then abstract items away.
I wrote a blog post on writing maintainable tests here.
You can see my blog post on the Page object model here
So your object could be like below.
public class Home
{
private readonly ISelenium _selenium;
/// <summary>
/// Instantiates a new Home Page object. Pass in the Selenium object created in the test SetUp().
/// When the object in instantiated it will navigate to the root
/// </summary>
/// <param name="selenium">Selenium Object created in the tests
public Home(ISelenium selenium)
{
this._selenium = selenium;
if (!selenium.GetTitle().Contains("home"))
{
selenium.Open("/");
}
}
/// <summary>
/// Navigates to Selenium Tutorials Page. Selenium object wll be passed through
/// </summary>
/// <returns>SeleniumTutorials representing the selenium_training.htm</returns>
public SeleniumTutorials ClickSelenium()
{
_selenium.Click("link=selenium");
_selenium.WaitForPageToLoad("30000");
return new SeleniumTutorials(_selenium);
}
/// <summary>
/// Click on the blog or blog year and then wait for the page to load
/// </summary>
/// <param name="year">blog or blog year
/// <returns>Object representing /blog.* pages</returns>
public Blog ClickBlogYear(string year)
{
_selenium.Click("link=" + year);
_selenium.WaitForPageToLoad("30000");
return new Blog(_selenium);
}
// Add more methods as you need them
}
public class SeleniumXPathTutorial
{
private readonly ISelenium _selenium;
public const string FirstInput = "number1";
public const string SecondInput = "number2";
public const string Total = "total";
public SeleniumXPathTutorial(ISelenium selenium)
{
this._selenium = selenium;
}
public bool IsInputOnScreen(string locator)
{
return _selenium.IsElementPresent(locator);
}
}
and then the test class would be like
[TestFixture]
public class SiteTests
{
private ISelenium selenium;
[SetUp]
public void Setup()
{
selenium = new DefaultSelenium("localhost", 4444, "*chrome", "http://www.theautomatedtester.co.uk");
selenium.Start();
}
[TearDown]
public void Teardown()
{
selenium.Stop();
}
[Test]
public void ShouldLoadHomeThenGoToXpathTutorial()
{
Home home = new Home(selenium);
SeleniumTutorials seleniumTutorials = home.ClickSelenium();
SeleniumXPathTutorial seleniumXPathTutorial = seleniumTutorials.ClickXpathTutorial();
Assert.True(seleniumXPathTutorial.
IsInputOnScreen(SeleniumXPathTutorial.FirstInput));
Assert.True(seleniumXPathTutorial
.IsInputOnScreen(SeleniumXPathTutorial.SecondInput));
Assert.True(seleniumXPathTutorial
.IsInputOnScreen(SeleniumXPathTutorial.Total));
}
}

Designing Business Objects to indicate constraints such as Max Length

Is there a standard convention when designing business objects for providing consumers with a way to discover constraints such as a property's maximum length?
It could be used up in the UI layer to, for example, set a Textbox's MaxLength property according to the maximum length limit back in the business object.
Is there a standard design approach for this?
Validation frameworks often contain parts for integrating with UI technologies in communicating the errors. Microsoft Enterprise Library Validation Application Block for instance contains a ValidationProvider extender control for WinForms that binds with the WinForms ErrorProvider control.
Your wish is different though. You want to communicate the constraints before they turn in to errors. Because this is not a standard requirement, I don't believe most validation frameworks have something for this out of the box. However, depending on the chosen framework creating this might be achievable. The Validation Application Block for instance, allows you to analyze the rules that you have registered / configured on a entity. So it is possible to build a control that will do this for you.
[Edit]
What you could also do is validate a form immediately upon startup and after each keystroke. This causes error icons or messages to show up immediately, which allows users to directly see what the constraints are (when you use icons, the user can hover an icon to see the error message). This isn't perhaps as nice as creating your own control, but it much easier to implement.
I have my own validation framework that lets me validate each field with the help of designated ValidationAttribute. It uses Attributes to automate most of the validations.
A sample business object would look like this in my application.
Each business object would inherit from EntityBase abstract class that has a public method called "Validate()". When this method is called on the given instance of the business object it will iterate through all properties of its own having Attributes that are derived from ValidationAttribute can call ValidationAttriubte's IsValid method to validate the value of associated proerty and return true/false with err. msg if any.
User.cs
[TableMapping("Users")]
public class User : EntityBase
{
#region Constructor(s)
public AppUser()
{
BookCollection = new BookCollection();
}
#endregion
#region Properties
#region Default Properties - Direct Field Mapping using DataFieldMappingAttribute
private System.Int32 _UserId;
private System.String _FirstName;
private System.String _LastName;
private System.String _UserName;
private System.Boolean _IsActive;
[DataFieldMapping("UserID")]
[DataObjectFieldAttribute(true, true, false)]
[NotNullOrEmpty(Message = "UserID From Users Table Is Required.")] // VALIDATION ATTRIBUTE
public override int Id
{
get
{
return _UserId;
}
set
{
_UserId = value;
}
}
[DataFieldMapping("UserName")]
[Searchable]
[NotNullOrEmpty(Message = "Username Is Required.")] // VALIDATION ATTRIBUTE
public string UserName
{
get
{
return _UserName;
}
set
{
_UserName = value;
}
}
[DataFieldMapping("FirstName")]
[Searchable]
public string FirstName
{
get
{
return _FirstName;
}
set
{
_FirstName = value;
}
}
[DataFieldMapping("LastName")]
[Searchable]
public string LastName
{
get
{
return _LastName;
}
set
{
_LastName = value;
}
}
[DataFieldMapping("IsActive")]
public bool IsActive
{
get
{
return _IsActive;
}
set
{
_IsActive = value;
}
}
#region One-To-Many Mappings
public BookCollection Books { get; set; }
#endregion
#region Derived Properties
public string FullName { get { return this.FirstName + " " + this.LastName; } }
#endregion
#endregion
public override bool Validate()
{
bool baseValid = base.Validate();
bool localValid = Books.Validate();
return baseValid && localValid;
}
}
BookCollection.cs
/// <summary>
/// The BookCollection class is designed to work with lists of instances of Book.
/// </summary>
public class BookCollection : EntityCollectionBase<Book>
{
/// <summary>
/// Initializes a new instance of the BookCollection class.
/// </summary>
public BookCollection()
{
}
/// <summary>
/// Initializes a new instance of the BookCollection class.
/// </summary>
public BookCollection (IList<Book> initialList)
: base(initialList)
{
}
}
Custom Attributes might serve your need.