QueryableDataServiceCollectionView - The DataServiceCollection to be tracked must contain entity typed elements with at least one key property.

9 posts, 1 answers
  1. Stevo
    Stevo avatar
    25 posts
    Member since:
    Jun 2013

    Posted 08 Oct 2013 Link to this post

    Hi,

    I'd like to display data from database using an OData endpoint in the GridView. For this I've decided to use the QueryableDataServiceCollectionView, passing the DataServiceContext and DataServiceQuery into constructor.

    For OData, I have a standard setup of Web Api OData Service endpoint and WCF Data Services 5 WPF Client. Model (DTO) looks like this:

    [DataServiceKey("FactTradeHeaderIdentifier")]
        public class TradeHeaderModel
        {
            [Key]
            [DataMember(IsRequired = true)]               
            public int FactTradeHeaderIdentifier { get; set; }
         
            ...
        }

    And the autogenerated client side counterpart like this:

        /// <summary>
        /// There are no comments for Edft.Regulatory.Tracker.Service.Web.ApiModels.TradeHeaderModel in the schema.
        /// </summary>
        /// <KeyProperties>
        /// FactTradeHeaderIdentifier
        /// </KeyProperties>
        [global::System.Data.Services.Common.EntitySetAttribute("TradeHeaders")]
        [global::System.Data.Services.Common.DataServiceKeyAttribute("FactTradeHeaderIdentifier")]
        public partial class TradeHeaderModel : global::System.ComponentModel.INotifyPropertyChanged
        {
            /// <summary>
            /// There are no comments for Property FactTradeHeaderIdentifier in the schema.
            /// </summary>
            [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Data.Services.Design", "1.0.0")]
            public int FactTradeHeaderIdentifier
            {
                get
                {
                    return this._FactTradeHeaderIdentifier;
                }
                set
                {
                    this.OnFactTradeHeaderIdentifierChanging(value);
                    this._FactTradeHeaderIdentifier = value;
                    this.OnFactTradeHeaderIdentifierChanged();
                    this.OnPropertyChanged("FactTradeHeaderIdentifier");
                }
            }
     
            ...
    }

    When loading data into the QueryableDataServiceCollectionView 

    var ds = new QueryableDataServiceCollectionView<TradeHeaderModel>(apiService.Container, apiService.Container.TradeHeaders);

    I get this error:

    System.ArgumentException: The DataServiceCollection to be tracked must contain entity typed elements with at least one key property. The element type 'Edft.Regulatory.Tracker.Presentation.CrossCutting.ServiceClient.ApiODataService.TradeHeaderModel' does not have any key property.
       at System.Data.Services.Client.DataServiceCollection`1.StartTracking(DataServiceContext context, IEnumerable`1 items, String entitySet, Func`2 entityChanged, Func`2 collectionChanged)
       at System.Data.Services.Client.DataServiceCollection`1..ctor(DataServiceContext context)
       at Telerik.Windows.Controls.DataServices.DataServiceCollection`1..ctor(DataServiceContext context)
       at Telerik.Windows.Data.QueryableDataServiceCollectionView`1..ctor(DataServiceContext dataServiceContext, DataServiceQuery`1 dataServiceQuery)
       at Edft.Regulatory.Tracker.Presentation.Modules.Dashboard.ViewModels.TradeHeaderViewModel.<LoadDataAsync>d__1f.MoveNext() in d:\TFS\Regulatory\Tracker\Dev\Codebase\Edft.Regulatory.Tracker.Presentation.Modules.Dashboard\ViewModels\TradeHeaderViewModel.cs:line 272

    Note that the DataServiceKeyAttribute is defined on both client and server models.

    Any ideas? 


    Edit: Using the Telerik.Windows.Controls.DataServices50 version

    Thanks,
    Stevo

  2. Rossen Hristov
    Admin
    Rossen Hristov avatar
    2478 posts

    Posted 08 Oct 2013 Link to this post

    Hello,

    We simply use the standard Microsoft class DataServiceCollection as described here. We don't actually perform any of the WCF Data Services work -- we simply append Where and OrderBy's on the query -- that's it. Our component simply steps on top of the WCF Data Services stack and its only job is to append those Where and OrderBy clauses to the DataServiceQuery<T>. It does not do anything else -- all the job is done by the DataServiceContext, DataServiceCollection and DataServiceQuery.

    From the stack trace I can see that it is the DataServiceCollection that complains about the query.
     
    I have the following question. If you remove all Telerik components, can you successfully create and use such a DataServiceCollection<T> to make queries as described in this article?

    Please, let me know what the results are.

    Regards,
    Rossen Hristov
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  3. UI for WPF is Visual Studio 2017 Ready
  4. Stevo
    Stevo avatar
    25 posts
    Member since:
    Jun 2013

    Posted 08 Oct 2013 Link to this post

    Hi Rossen,

    I've tried to use the DataServiceCollection<T> directly, passing it DataServiceQuery<T> appended with same .Where(...) (which makes it IQueryable<T>) and that works fine.

    However that strips away the possibility of doing server side sorting and paging.

    Regards,
    Stevo
  5. Rossen Hristov
    Admin
    Rossen Hristov avatar
    2478 posts

    Posted 08 Oct 2013 Link to this post

    Hello,

    I don't really think that this exception is caused by our components. In fact I am sure that it is not by reading the stack trace you posted. The exception is thrown the very moment we try to create this DataServiceCollection with the supplied arguments.

    Here is what we do in our very thin wrapper:

    var something = new DataServiceCollection<TradeHeaderModel>(apiService.Container);

    And at exactly this point it throws the exception. I am baffled by the fact that you can successfully do the same thing "outside" and not get any exceptions. Is this so?

    Regards,
    Rossen Hristov
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  6. Stevo
    Stevo avatar
    25 posts
    Member since:
    Jun 2013

    Posted 09 Oct 2013 Link to this post

    Hi,

    just tried:

    var data = new DataServiceCollection<TradeHeaderModel>(apiService.Container.TradeHeaders); // Works Fine

    var data = new QueryableDataServiceCollectionView<TradeHeaderModel>(apiService.Container, apiService.Container.TradeHeaders); //Crashes complaining about the missing key

    Note that what you've suggested
    var something = new DataServiceCollection<TradeHeaderModel>(apiService.Container);
    Does not do anything, since container does not have any data as such

    Regards,
    Stevo

  7. Rossen Hristov
    Admin
    Rossen Hristov avatar
    2478 posts

    Posted 09 Oct 2013 Link to this post

    Hello,

    The thing I suggested is exactly what we do in our constructor. Here is an excerpt from our souce code:

    this.wcfDataServiceCollection = new WCF.DataServiceCollection<TEntity>(this.context);

    Where TEntity in this case is TradeHeaderModel and this.context is the instance of DataServiceContext<T> that you supply in the constructor. It learns about the type from the generic argument as we will see later.

    Once we send the query to the server and receive the response we call DataServiceCollection.Load method to load all received entities in the DataServiceCollection. We simply follow what is written in MSDN here.

    Anyway, here is the stacktrace again:

    System.ArgumentException: The DataServiceCollection to be tracked must contain entity typed elements with at least one key property. The element type 'Edft.Regulatory.Tracker.Presentation.CrossCutting.ServiceClient.ApiODataService.TradeHeaderModel' does not have any key property.
       at System.Data.Services.Client.DataServiceCollection`1.StartTracking(DataServiceContext context, IEnumerable`1 items, String entitySet, Func`2 entityChanged, Func`2 collectionChanged)
       at System.Data.Services.Client.DataServiceCollection`1..ctor(DataServiceContext context)
       at Telerik.Windows.Controls.DataServices.DataServiceCollection`1..ctor(DataServiceContext context)
       at Telerik.Windows.Data.QueryableDataServiceCollectionView`1..ctor(DataServiceContext dataServiceContext, DataServiceQuery`1 dataServiceQuery)
       at Edft.Regulatory.Tracker.Presentation.Modules.Dashboard.ViewModels.TradeHeaderViewModel.<LoadDataAsync>d__1f.MoveNext() in d:\TFS\Regulatory\Tracker\Dev\Codebase\Edft.Regulatory.Tracker.Presentation.Modules.Dashboard\ViewModels\TradeHeaderViewModel.cs:line 272

    The things in yellow is the souce code I pasted above. We simply create a new instance of a generic System.Data.Services.Client.DataServiceCollection<TradeHeaderModel> by passing your context to the constructor. That is all. I reflected their assembly and here is the constructor:

    public DataServiceCollection(DataServiceContext context, IEnumerable<T> items, TrackingMode trackingMode, string entitySetName, Func<EntityChangedParams, bool> entityChangedCallback, Func<EntityCollectionChangedParams, bool> collectionChangedCallback)
    {
        if (trackingMode != TrackingMode.AutoChangeTracking)
        {
            if (items != null)
            {
                this.Load(items);
            }
        }
        else
        {
            if (context == null)
            {
                if (items != null)
                {
                    context = DataServiceCollection<T>.GetContextFromItems(items);
                }
                else
                {
                    this.trackingOnLoad = true;
                    this.entitySetName = entitySetName;
                    this.entityChangedCallback = entityChangedCallback;
                    this.collectionChangedCallback = collectionChangedCallback;
                }
            }
            if (!this.trackingOnLoad)
            {
                if (items != null)
                {
                    DataServiceCollection<T>.ValidateIteratorParameter(items);
                }
                this.StartTracking(context, items, entitySetName, entityChangedCallback, collectionChangedCallback);
                return;
            }
        }
    }

    And here is the StartTracking method I decompiled:

    private void StartTracking(DataServiceContext context, IEnumerable<T> items, string entitySet, Func<EntityChangedParams, bool> entityChanged, Func<EntityCollectionChangedParams, bool> collectionChanged)
    {
        if (BindingEntityInfo.IsEntityType(typeof(T), context.Model))
        {
            this.observer = new BindingObserver(context, entityChanged, collectionChanged);
            if (items != null)
            {
                try
                {
                    this.InternalLoadCollection(items);
                }
                catch
                {
                    this.observer = null;
                    throw;
                }
            }
            this.observer.StartTracking<T>(this, entitySet);
            this.rootCollection = true;
            return;
        }
        else
        {
            throw new ArgumentException(Strings.DataBinding_DataServiceCollectionArgumentMustHaveEntityType(typeof(T)));
        }
    }


    For some mystic reason the thing that tracks entities thinks that your class TradeHeaderModel does not have at least one Key property or that it is not an Entity at all. This is really beyond me. If you try with a dummy demo with AdventureWorks or Northwind you will see that all goes well, so there must be something funny in this TradeHeaderModel class but I do not know what it is.

    I really have no idea why the System.Data.Services.Client.DataServiceCollection does not like your TradeHeaderModel class.

    So basically you are saying that if you write this
    exact line somewhere in your project:

    var something = new System.Data.Services.Client
    DataServiceCollection<TradeHeaderModel>(<<your DataServiceContext instance here>>);


    and it does not blow? 

    That is very weird since we do this exact same thing and it blows up as you can see.

    Anyway, unless I am able to reproduce this locally, I can't really guess why Microsoft's System.Data.Services.Client.DataServiceCollection blows up.

    Also, please make sure that you are using WCF Data Services 5.5.0 or above which is the out-of-band version that our assembly Telerik.Windows.Controls.DataServices50.dll for .NET 4.5. Only the .NET 4.5 version of our assembly can target WCF Data Services 5 and above since Microsoft decided to start releasing WCF Data Services out-of-band and we can't really create a build for each of their version that are distributed via NuGet.

    Another thing -- if you don't do any CRUD operations, you don't really need our component - you can directly bind RadGridView to an IQueryable (i.e. the DataServiceQuery<T> on your context) and it will do all of its stuff on this IQueryable. This is described here.

    If you can help me reproduce this locally I will be more than glad to take a look. With the information I currently have my hands are kind of tied.

    Regards,
    Rossen Hristov
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  8. Stevo
    Stevo avatar
    25 posts
    Member since:
    Jun 2013

    Posted 09 Oct 2013 Link to this post

    Hi,

    >>The thing I suggested is exactly what we do in our constructor. Here is an excerpt from our souce code:

    this.wcfDataServiceCollection = new WCF.DataServiceCollection<TEntity>(this.context);

    Where TEntity in this case is TradeHeaderModel and this.context is the instance of DataServiceContext<T> that you supply in the constructor. It learns about the type from the generic argument as we will see later.

    Once we send the query to the server and receive the response we call DataServiceCollection.Load method to load all received entities in the DataServiceCollection. We simply follow what is written in MSDN here.

    Looking at MSDN, I don't understand why are you guys using that constructor. It's not meant for loading from server. http://msdn.microsoft.com/en-us/library/ee652763.aspx 

    You must be loading data somehow differently (and that's where I suppose the problem happens). All the MSDN examples show passing it the actual query:

    http://msdn.microsoft.com/en-us/library/ee373844.aspx
    http://msdn.microsoft.com/en-us/library/ee474331.aspx
    http://msdn.microsoft.com/en-us/library/ee373846.aspx

    >>var something = new System.Data.Services.Client
    DataServiceCollection<TradeHeaderModel>(<<your DataServiceContext instance here>>);

    and it does not blow?
     

    That does not do anything, and it's not mean to do http://msdn.microsoft.com/en-us/library/ee652763.aspx 

    >>Another thing -- if you don't do any CRUD operations, you don't really need our component - you can directly bind RadGridView to an IQueryable (i.e. the DataServiceQuery<T> on your context) and it will do all of its stuff on this IQueryable. This is described here.

    It's runs the queries on the UI thread, which we can't have for obvious reasons.

    Regards,
    Stevo

  9. Answer
    Rossen Hristov
    Admin
    Rossen Hristov avatar
    2478 posts

    Posted 09 Oct 2013 Link to this post

    Hello,

    The process is quite simple actually. We create an empty DataServiceCollection<T> in the very beginning. Then each time a load is requested for some reason we basically do the following. We call DataServiceContext.BeginExecute by passing the required query. This kicks off an async operation. After a while data comes back to the client. We then call context.EndExecute and obtain the entities. We then stick all of those entities in the DataServiceCollection by callind its Load method so it starts tracking them. Here is the complete source code of our thin wrapper class called Telerik.Windows.Controls.DataServices.DataServiceCollection. Note that while the name is the same, this is our class and not the System.Data.Services.Client.DataServiceCollection, which is the class we wrap and is called wcfDataServiceCollection in the source code:

    using System;
    using System.Collections;
    using System.ComponentModel;
    using System.Threading;
    using System.Windows;
    using System.Diagnostics;
    using System.Data.Services.Client;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Net;
    using Telerik.Windows.Data;
    using WCF = System.Data.Services.Client;
     
    namespace Telerik.Windows.Controls.DataServices
    {
        /// <summary>
        /// DataServiceCollection.
        /// </summary>
        internal class DataServiceCollection<TEntity> :
            ObservableItemCollection<TEntity>,
            INotifyPropertyChanged
            where TEntity : class, INotifyPropertyChanged
        {
            private readonly DataServiceContext context;
            private readonly WCF.DataServiceCollection<TEntity> wcfDataServiceCollection;
     
            public event EventHandler<LoadOperationCompletedEventArgs<TEntity>> LoadCompleted;
            private SynchronizationContext syncContext;
            private IAsyncResult currentLoadOperation;
            private bool cancelledRequest;
            private bool ignoreCollectionChangedOverride;
            private int totalItemCount = -1;
            private bool isLoading;
            private bool hasChanges;
     
            /// <summary>
            /// Gets the total item count.
            /// </summary>
            /// <value>The total item count.</value>
            public int TotalItemCount
            {
                get
                {
                    return this.totalItemCount;
                }
                private set
                {
                    if (this.totalItemCount != value)
                    {
                        this.totalItemCount = value;
                        this.OnPropertyChanged("TotalItemCount");
                    }
                }
            }
     
            public bool IsLoading
            {
                get
                {
                    return this.isLoading;
                }
                private set
                {
                    if (this.isLoading != value)
                    {
                        this.isLoading = value;
                        this.OnPropertyChanged("IsLoading");
                    }
                }
            }
             
            public bool HasChanges
            {
                get
                {
                    return this.hasChanges;
                }
                private set
                {
                    if (this.hasChanges != value)
                    {
                        this.hasChanges = value;
                        this.OnPropertyChanged("HasChanges");
                    }
                }
            }
             
            /// <summary>
            /// Initializes a new instance of the DataServiceCollection class.
            /// </summary>
            /// <param name="context">The context.</param>
            public DataServiceCollection(DataServiceContext context)
            {
                if (context == null)
                {
                    throw new ArgumentNullException("context");
                }
     
                this.context = context;
                this.wcfDataServiceCollection = new WCF.DataServiceCollection<TEntity>(this.context);
            }
     
            public void SetSynchronizationContext(SynchronizationContext synchronizationContext)
            {
                this.syncContext = synchronizationContext;
            }
     
            public void Load(LoadContext loadContext)
            {
                this.wcfDataServiceCollection.Clear(); 
                 
                var query = loadContext.DataServiceQuery;
                var queryRequestUri = query.RequestUri;
     
                this.IsLoading = true;
                 
                // Any other option will break the inner logic.
                if (this.context.MergeOption != MergeOption.OverwriteChanges)
                {
                    throw new InvalidOperationException("DataServiceContext.MergeOption can only be MergeOption.OverwriteChanges.");
                }
     
                this.currentLoadOperation = this.context.BeginExecute<TEntity>(queryRequestUri
                    , this.OnResultsReceived
                    , loadContext);
            }
     
            public void CancelLoad()
            {
                if (this.currentLoadOperation != null
                    && !this.currentLoadOperation.IsCompleted)
                {
                    this.cancelledRequest = true;
                    try
                    {
                        this.context.CancelRequest(this.currentLoadOperation);
                    }
                    catch (WebException)
                    {
                    }
                }
            }
     
            /// <summary>
            /// Called when the results arrive asynchronously from the server.
            /// </summary>
            /// <remarks>
            /// Since there is no guarantee that this method will be invoked on the UI thread,
            /// we have to marshal the response operation back to the main application thread
            /// (the UI thread). Code that accesses entities, accesses the DataServiceContext or
            /// enumerates results of LINQ queries needs to happen on the UI thread.
            /// </remarks>
            /// <param name="result">The result.</param>
            private void OnResultsReceived(IAsyncResult result)
            {
                this.syncContext.Post(delegate(object state)
                {
                    this.SynchronizeContextLoadCompleted(result);
                }, null
                );
            }
     
            [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
            private void SynchronizeContextLoadCompleted(IAsyncResult result)
            {
                if (this.cancelledRequest)
                {
                    this.cancelledRequest = false;
                    this.currentLoadOperation = null;
                     
                    this.IsLoading = false;
                    var args = new LoadOperationCompletedEventArgs<TEntity>(Enumerable.Empty<TEntity>()
                        , null
                        , (LoadContext)result.AsyncState
                        , true
                        , null
                        , 0);
                    this.OnLoadCompleted(args);
                }
                else
                {
                    QueryOperationResponse<TEntity> response = null;
     
                    try
                    {
                        response = (QueryOperationResponse<TEntity>)this.context.EndExecute<TEntity>(result);
                    }
                    catch (Exception exception)
                    {
                        this.IsLoading = false;
                        var args = new LoadOperationCompletedEventArgs<TEntity>(Enumerable.Empty<TEntity>()
                            , response
                            , (LoadContext)result.AsyncState
                            , false
                            , exception
                            , 0);
                        this.OnLoadCompleted(args);
     
                        return;
                    }
     
                    if (response != null)
                    {
                        this.ProcessResponse(response, (LoadContext)result.AsyncState);
                    }
                }
            }
             
            private void ProcessResponse(QueryOperationResponse<TEntity> response, LoadContext loadContext)
            {
                //// Load the entities that have just arrived in the "state"
                //// DataServiceCollection so it can start "tracking" them.
                //// response is an IEnumerable<T> and contains the entities
                this.wcfDataServiceCollection.Load(response);
     
                var continuation = response.GetContinuation();
                if (continuation != null)
                {
                    // Send a request for the next server page.
                    this.currentLoadOperation = this.context.BeginExecute<TEntity>(continuation
                        , this.OnResultsReceived, loadContext);
                }
                else
                {
                    this.IsLoading = false;
                 
                    // This was the last page, so copy all the entities to "this".
                    this.SuspendNotifications();
     
                    this.ignoreCollectionChangedOverride = true;
                    this.Clear();
                    this.AddRange(this.wcfDataServiceCollection);
                    this.ignoreCollectionChangedOverride = false;
                     
                    try
                    {
                        this.TotalItemCount = (int)response.TotalCount;
                    }
                    catch (InvalidOperationException)
                    {
                        // The server refuses to tell us the total count for some reason.
                        // Most probably the DataServiceBehavior has its
                        // AcceptCountRequests set to false.
                        // Set the TotalItemCount to be as much as we know.
                        // Nothing better that we can do. Bad server, bad!
                        this.TotalItemCount = this.Count;
                    }
                     
                    this.ResumeNotifications();
                }
     
                var args = new LoadOperationCompletedEventArgs<TEntity>(this.wcfDataServiceCollection
                    , response
                    , loadContext
                    , false
                    , null
                    , this.TotalItemCount);
                this.OnLoadCompleted(args);
            }
     
            protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
            {
                base.OnCollectionChanged(e);
     
                if (this.ignoreCollectionChangedOverride)
                {
                    return;
                }
     
                switch (e.Action)
                {
                    case NotifyCollectionChangedAction.Add:
                        foreach (TEntity item in e.NewItems)
                        {
                            this.wcfDataServiceCollection.Add(item);
                            this.TotalItemCount++;
                        }
                        break;
                    case NotifyCollectionChangedAction.Remove:
                        foreach (TEntity item in e.OldItems)
                        {
                            this.wcfDataServiceCollection.Remove(item);
                            this.TotalItemCount--;
                        }
                        break;
                    case NotifyCollectionChangedAction.Replace:
                        break;
                    case NotifyCollectionChangedAction.Reset:
                        break;
                    default:
                        break;
                }
     
                this.RefreshHasChanges();
            }
     
            protected override void OnItemChanged(ItemChangedEventArgs<TEntity> e)
            {
                base.OnItemChanged(e);
     
                this.RefreshHasChanges();
            }
     
            public void RefreshHasChanges()
            {
                this.HasChanges = this.context.HasChanges();
            }
     
            private void OnPropertyChanged(string propertyName)
            {
                this.OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
            }
     
            protected virtual void OnLoadCompleted(LoadOperationCompletedEventArgs<TEntity> args)
            {
                var handler = this.LoadCompleted;
                if (handler != null)
                {
                    handler(this, args);
                }
            }
        }
    }

    Yes, creating a new empty instance of DataServiceCollection<T>(context) does not do anything immediately (at this exact moment) but this is where your exception occurs, which is why I asked you several times for to simply try this line of code outside our component, which you for some reason are refusing to do. I can't really fix an exception that is thrown by WCF Data Services when this line is written:

    var sth = new DataServiceCollection<T>(context);

    This is one of the constructors that Microsoft provides (so it has a point after all) and our software happens to use this constructor for the reasons I explained above. This constructor thows an exception. All we pass to this constructor are the two thing provied by you -- the generic type TradeHeaderMode and the DataServiceContext that you have provided. We don't do anything in between.

    This is why I asked you several times to just execute this line:

    var sth = new DataServiceCollection<T>(context);

    And tell me what the results are. Up until now I have not received an answer.

    If you can provide a runnable sample project which I can debug locally I might be able to help you. But unless I have that I really don't know what else I can do about this issue.

    Regards,

    Rossen Hristov
    Telerik
    TRY TELERIK'S NEWEST PRODUCT - EQATEC APPLICATION ANALYTICS for WPF.
    Learn what features your users use (or don't use) in your application. Know your audience. Target it better. Develop wisely.
    Sign up for Free application insights >>
  10. Stevo
    Stevo avatar
    25 posts
    Member since:
    Jun 2013

    Posted 29 Oct 2013 Link to this post

    Hi,

    I've started drilling into the problem again, and it just started working. I'm not sure what has changed in the meantime, I remember updating Telerik dlls to latest version, maybe some other references have changed and the problem disappeared.

    Thanks for your support,
    Stevo
Back to Top
UI for WPF is Visual Studio 2017 Ready