Link to home
Create AccountLog in
Avatar of vpit
vpit

asked on

Silverlight not showing data when binding with WCF Data Service

I am trying to create a simple SQL 2008 databound control with Silverlight and my grid is not showing any data. I have used the MSDN Walkthrough: Binding Silverlight Controls to a WCF Data Service at this URL http://msdn.microsoft.com/en-us/library/ee621313.aspx There are no glaring errors in my code and it compiles just fine. When I debug, my controls display but have no data.  Why? Please help ... I have included some code as shown below ...

MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Data;
using ConflictSearchApp.ConflictSearchService;

namespace ConflictSearchApp
{
    public partial class MainPage : UserControl
    {
        private Matter_SearchEntities conflictService;
        private System.Windows.Data.CollectionViewSource matterViewSource;

        public MainPage()
        {
            InitializeComponent();
            
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            conflictService = new Matter_SearchEntities(new Uri("http://localhost:39291/SearchDataService.svc"));
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
             {
             	//Load your data here and assign the result to the CollectionViewSource.
             	System.Windows.Data.CollectionViewSource matterViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["matterViewSource"];
                matterViewSource.Source = conflictService.Matter_Subs.BeginExecute(result => matterViewSource.Source = conflictService.Matter_Subs.EndExecute(result), null);
             }
        }
    }
}

Open in new window

SearchDataServices.svc
using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Data.Services.Common;
using System.Linq;
using System.ServiceModel.Web;
using System.Web;

namespace ConflictSearch
{
    public class SearchDataService : DataService< Matter_SearchEntities >
    {        
        public static void InitializeService(DataServiceConfiguration config)
        {            
            config.SetEntitySetAccessRule("*", EntitySetRights.All);
            config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
        }
    }
}

Open in new window

I also have a ConflictSearchDataModel.edmx page that is my data model of the SQL table I am targeting.

Any ideas why I can't show the data in my controls?

Thanks in advance.
Avatar of Aaron Jabamani
Aaron Jabamani
Flag of United Kingdom of Great Britain and Northern Ireland image

You are populating the view source but you are not binding to the datacontext. Try below and also hope it goes inside the If LOOP.


private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            conflictService = new Matter_SearchEntities(new Uri("http://localhost:39291/SearchDataService.svc"));
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
             {
                   //Load your data here and assign the result to the CollectionViewSource.
                   System.Windows.Data.CollectionViewSource matterViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["matterViewSource"];
                matterViewSource.Source = conflictService.Matter_Subs.BeginExecute(result => matterViewSource.Source = conflictService.Matter_Subs.EndExecute(result), null);

            this.Datacotext = matterViewSource;

             }
        }
Avatar of vpit
vpit

ASKER

Still not working.
Here is my constructor:
private Matter_SearchEntities conflictService;
        private System.Windows.Data.CollectionViewSource matterViewSource;

public MainPage()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(UserControl_Loaded);
            
        }

Open in new window

And here is my UserControl_Loaded method:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
conflictService = new Matter_SearchEntities(new Uri("http://localhost:19924/SearchDataService.svc"));
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            {
                //Load your data here and assign the result to the CollectionViewSource.
                System.Windows.Data.CollectionViewSource matterViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["matterViewSource"];
                matterViewSource.Source = conflictService.Matter_Subs.BeginExecute(result => matterViewSource.Source = conflictService.Matter_Subs.EndExecute(result), null);

                this.DataContext = matterViewSource;

            }

Open in new window

If you debug you can see the data in the source , matterviewsource object?  And can I see your xaml ?
Avatar of vpit

ASKER

Ok, I have changed some things around ... basically starting over, but I think I have a better base now. I have created a Visual Studio solution with WCF projects as tiered layers. I have a Data Access Layer, Entities Layer, Logic Layer and Service Layer. When I run the solution I am able to successfully get to my SQL database and view tabular data.
My next step is to add a Silverlight project to the solution and bind the data to a grid. This is where I get stuck. I think my errors lay in the XAML.cs file in that I am not binding my Service correctly, but I don't know how to fix it. The code that is in-place in the XAML.cs is broken. I have my database connectionString data inside my App.config file (which I have not displayed here).  Let me show you the code for my pages:


Data Access Layer
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using myWCFServices.RealWorldEntities;
using System.Data.SqlClient;
using System.Configuration;

namespace myWCFServices.RealWorldDAL
{
    public class ProductDAO
    {
        string connectionString = ConfigurationManager.ConnectionStrings["MatterSubsConnectionString"].ConnectionString;

        public ProductEntity GetProduct(int id)
        {
            // TODO: connect to DB to retrieve product
            
            ProductEntity p = null;
            using (SqlConnection conn = new SqlConnection(connectionString))
            {
                SqlCommand comm = new SqlCommand();
                comm.CommandText = "select * from Matter_Subs";
                comm.Connection = conn;
                conn.Open();
                SqlDataReader reader = comm.ExecuteReader();
                if(reader.HasRows)
                {
                    reader.Read();
                    p = new ProductEntity();
                    p.RecordID = id;
                    p.ClientNumber = (string)reader["Client_Number"];
                    p.ClientName = (string)reader["Client_Name"];
                    p.BillingAtty = (string)reader["Billing_Atty"];
                }
            }
            return p;
        }

        public bool UpdateProduct(ProductEntity product)
        {
            // TODO: connect to DB to update product
            return true;
        }
    }
}

Open in new window

Logic Layer
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using myWCFServices.RealWorldEntities;
using myWCFServices.RealWorldDAL;

namespace myWCFServices.RealWorldLogic
{
    public class ProductLogic
    {
        ProductDAO productDAO = new ProductDAO();

        public ProductEntity GetProduct(int id)
        {
            return productDAO.GetProduct(id);
        }
    }
}

Open in new window

Entities Layer
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace myWCFServices.RealWorldEntities
{
    public class ProductEntity
    {
        public int RecordID { get; set; }
        public string ClientName { get; set; }
        public string BillingAtty { get; set; }
        public string ClientNumber { get; set; }
    }
}

Open in new window

Service Layer
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using myWCFServices.RealWorldEntities;
using myWCFServices.RealWorldLogic;

namespace myWCFServices.RealWorldService
{
    public class ProductService : IProductService
    {
        public Product GetProduct(int id)
        {            
            ProductLogic productLogic = new ProductLogic();
            ProductEntity productEntity = productLogic.GetProduct(id);
            Product product = new Product();
            TranslateProductEntityToProductContractData(productEntity, product);
            return product;
        }

        private void TranslateProductEntityToProductContractData(ProductEntity productEntity, Product product)
        {
            product.RecordID = productEntity.RecordID;
            product.ClientName = productEntity.ClientName;
            product.ClientNumber = productEntity.ClientNumber;
            product.BillingAtty = productEntity.BillingAtty;
        }

        public bool UpdateProduct(Product product)
        {
            // TODO: call business logic layer to update product
            if(product.RecordID == null)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
    }
}

Open in new window

IProductServices.cs file
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace myWCFServices.RealWorldService
{
    [ServiceContract]
    public interface IProductService
    {
        [OperationContract]
        Product GetProduct(int id);

        [OperationContract]
        bool UpdateProduct(Product product);

    }

    [DataContract]
    public class Product
    {
        [DataMember]
        public int RecordID { get; set; }

        [DataMember]
        public string ClientName { get; set; }

        [DataMember]
        public string BillingAtty { get; set; }

        [DataMember]
        public string ClientNumber { get; set; }
    }
}

Open in new window

XAML
<UserControl x:Class="slRealWorld.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:my="clr-namespace:slRealWorld.ServiceReference1" Loaded="UserControl_Loaded">
    <UserControl.Resources>
        <CollectionViewSource x:Key="productViewSource" d:DesignSource="{d:DesignInstance my:Product, CreateList=True}" />
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid DataContext="{StaticResource productViewSource}" HorizontalAlignment="Left" Margin="46,12,0,0" Name="grid1" VerticalAlignment="Top">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto" />
                <ColumnDefinition Width="Auto" />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
                <RowDefinition Height="Auto" />
            </Grid.RowDefinitions>
            <sdk:Label Content="Billing Atty:" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" Grid.Row="0" Height="23" HorizontalAlignment="Left" Margin="3" Name="billingAttyTextBox" Text="{Binding Path=BillingAtty, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />
            <sdk:Label Content="Client Name:" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="3" Name="clientNameTextBox" Text="{Binding Path=ClientName, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />
            <sdk:Label Content="Client Number:" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="3" Name="clientNumberTextBox" Text="{Binding Path=ClientNumber, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />
            <sdk:Label Content="Record ID:" Grid.Column="0" Grid.Row="3" HorizontalAlignment="Left" Margin="3" VerticalAlignment="Center" />
            <TextBox Grid.Column="1" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="3" Name="recordIDTextBox" Text="{Binding Path=RecordID, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" VerticalAlignment="Center" Width="120" />
        </Grid>
    </Grid>
</UserControl>

Open in new window

XAML Code-Behind
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using slRealWorld.ServiceReference1;

namespace slRealWorld
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            
            ProductServiceClient newObj = new ProductServiceClient();
            
            newObj.GetProductCompleted += new EventHandler<getProductCompletedEventArgs>(DisplayResults);
            newObj.getProductAsync(1);
        }

        void DisplayResults(object sender, getProductCompletedEventArgs e)
        {
            LayoutRoot.DataContext = e.Result;   
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
        }
    }
}

Open in new window

Instead of <Grid DataContext="{StaticResource productViewSource}" ....

Use <Grid itemsource={binding} .....


Since you are assigning the datacontext in .cs file
Avatar of vpit

ASKER

itemsource is not a property of my Grid. It does not exist in my intellisense context menu.
Avatar of vpit

ASKER

Am I using the wrong initial project type? I started out with a "Silverlight Application", however, should I start with something else? Maybe another project type has other inherent binding properties I can leverage? Could the problem be a .Net framework issue? I believe I am using 4.0. There has to be a reason why my connections to the data are not working. An interesting note ... when I create static, hard-coded data and try to display that in my controls it does not work either. My controls remain empty of data whether I try to use hard-coded data or a web-service. I'm stumped at what I am missing .... any ideas?
Please ignore what i told you earlier.

Only remove DataContext="{StaticResource productViewSource}"  property of the Grid Control and check.

Also how you are using <sdk:Label .... since sdk namespace is not at all defined in your xaml. ...how is it your code getting complied ?   Instead of this use the silverlight control <Textblock>
Avatar of vpit

ASKER

Here is the sdk namespace reference:
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"

I tried your suggestion and still nothing. I also tried another solution found at http://www.dotnetcurry.com/ShowArticle.aspx?ID=228 with the same result. The development of the code went smoothly, but when it was executed to to the browser it showed nothing. My grid was again empty. I am getting the feeling there is something critical I am missing since each test I attempt gets the same empty results.

I put debug stops on my Service.svc page on the SQL ConnectionString and when I debugged the code the breaks on the ConnectionString page stated "The breakpoint will not currently be hit. No symbols have been loaded for this document." Any idea what this means? or how it may relate to my previous erroneous code attempt?
Avatar of vpit

ASKER

Ok, in my debugger I validated that my [OperationContract] is indeed pulling real data. But why then are my page controls still empty? What binding am I missing that links the returned "clientList" to the page congrols (i.e. DataGrid)?
So when you debug your silverlight .cs(below method, e.Result) file you can see the data coming in ?

void DisplayResults(object sender, getProductCompletedEventArgs e)
        {
            LayoutRoot.DataContext = e.Result;  
        }

also, calling the service logic move from constructor to loaded event like below...


Select allOpen in new window


XAML Code-Behind





using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using slRealWorld.ServiceReference1;

namespace slRealWorld
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
           
           
        }

        void DisplayResults(object sender, getProductCompletedEventArgs e)
        {
            LayoutRoot.DataContext = e.Result;  
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
                   ProductServiceClient newObj = new ProductServiceClient();
           
            newObj.GetProductCompleted += new EventHandler<getProductCompletedEventArgs>(DisplayResults);
            newObj.getProductAsync(1);
        }
    }
}
Avatar of vpit

ASKER

It turns out that the source of the problem was a combination of things, such as: the web.config file, and the C# in the code-behind page, but the largest sore thumb appears to be the query string for the datasource. I found that if I limited the query results it resulted in a populated DataGrid. I initially discovered this when changing my query to "Select Top 10 ..." and then continued testing to discover that I was able to pull 16300 rows successfully, however, when I attempted to pull 16400 rows I got an error. Why does this exist? I don't know. I have not found an answer to this, but my code does successfully return a result.
Avatar of vpit

ASKER

Please close.
There is always a limit you can pull data from a server by using any service.

Hope below link helps you.

http://msdn.microsoft.com/en-us/library/ee358709.aspx
ASKER CERTIFIED SOLUTION
Avatar of vpit
vpit

Link to home
membership
Create a free account to see this answer
Signing up is free and takes 30 seconds. No credit card required.
See answer
Avatar of vpit

ASKER

My answer was the only correct one.