0
votes

I have a series of web parts I need to implement in SharePoint 2010. The data provider web part uses an UpdatePanel and asynchronously makes a web service call which can potentially be slow. To keep it simple, I've put a single consumer web part on the page (Chart) which will use the consumer as its data provider.

My problem is that I can't get the consumer to wait for the provider - I get a variety of errors but all basically come back to "There is no data available". This may be because it is a Chart web part but the question also applies to the other custom parts I will be developing as they will pull the same data.

The question is: how do I either push data to my consumers when my provider is ready or somehow let them wait for my provider to have data (via polling or whatever).

Note: this is just a prototype, I haven't added error handling, etc yet.

Code is below:

[ToolboxItem(true)]
public partial class ClarityProjectGeneral : System.Web.UI.WebControls.WebParts.WebPart , IWebPartTable
{

    public DataTable ProjectVitals = new DataTable(); For web part communication

    // bunch of properties

    protected override void OnInit(EventArgs e)
    {
        base.OnInit(e);
        InitializeControl();

        // For web part communication
        // Initialize our datatable so the chart doesn't barf
        DataColumn col = new DataColumn();
        col.DataType = typeof(string);
        col.ColumnName = "Name";
        this.ProjectVitals.Columns.Add(col);

        col = new DataColumn();
        col.DataType = typeof(DateTime);
        col.ColumnName = "Start";
        this.ProjectVitals.Columns.Add(col);

        col = new DataColumn();
        col.DataType = typeof(DateTime);
        col.ColumnName = "End";
        this.ProjectVitals.Columns.Add(col);
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        loading.Visible = true;
        content.Visible = false;            
    }

    public ClarityObjectClasses.Projects GetProject(string projectID)
    {
        Clarity.ClarityAbstractorProject ca = new Clarity.ClarityAbstractorProject(this.Username, this.Password);
        Dictionary<string, string> queryParams = new Dictionary<string, string>();
        queryParams.Add("projectID", projectID);
        // Class for making web service call
        ClarityObjectClasses.Projects response = new ClarityObjectClasses.Projects();
        response = ca.GetProject(queryParams);
        return response;
    }

    protected void Timer1_Tick(object sender, EventArgs e)
    {
        if (this.ProjectID == null || this.Username == null || this.Password == null)
        {
            lblConfigError.Visible = true;
            lblConfigError.Text = "One or more required configuration values are not set.  Please check the web part configuration.";
            panelProjectDetails.Visible = false;
        }
        else
        {
            loading.Visible = true;
            content.Visible = false;

            panelProjectDetails.Visible = true;
            ClarityObjectClasses.Projects projects = GetProject(this.ProjectID);
            //Assign a bunch of values

            // For web part communication
            LoadTable(projects.Project[0]);

            Timer1.Enabled = false;
            loading.Visible = false;
            content.Visible = true;
        }
    }


    /* Interface functions for Graph Chart communication */
    For web part communication
    protected void LoadTable(ClarityObjectClasses.Project project)
    {
        DataRow row = ProjectVitals.NewRow();
        row["Name"] = project.name;
        row["Start"] = project.start;
        row["End"] = project.finish;
        this.ProjectVitals.Rows.Add(row);
    }

    public PropertyDescriptorCollection Schema
    {
        get
        {
            return TypeDescriptor.GetProperties(ProjectVitals.DefaultView[0]);
        }
    }

    public void GetTableData(TableCallback callback)
    {
        callback(ProjectVitals.Rows);
    }

    public bool ConnectionPointEnabled
    {
        get
        {
            object o = ViewState["ConnectionPointEnabled"];
            return (o != null) ? (bool)o : true;
        }
        set
        {
            ViewState["ConnectionPointEnabled"] = value;
        }
    }

    [ConnectionProvider("Table", typeof(TableProviderConnectionPoint), AllowsMultipleConnections = true)]
    public IWebPartTable GetConnectionInterface()
    {
        return this;
    }

    public class TableProviderConnectionPoint : ProviderConnectionPoint
    {
        public TableProviderConnectionPoint(MethodInfo callbackMethod, Type interfaceType, Type controlType, string name, string id, bool allowsMultipleConnections)
            : base(callbackMethod, interfaceType, controlType, name, id, allowsMultipleConnections)
        {
        }

        public override bool GetEnabled(Control control)
        {
            return ((ClarityProjectGeneral)control).ConnectionPointEnabled;
        }

    }
}
2
Hi, how did it go for you? I'm up to do the same thing and wonder if it's possible?Tim

2 Answers

0
votes

Do not quite understand, but if it helps You may not use "connectable" web-parts inside UpdatePanel, because of lack of corresponding events to bind data on asynchronous callback.

0
votes

I just stumbled across this. I had exactly the same problem trying to implement a custom webpart just as a proof to myself. I applied filters to both my webpart and a list, and then let a chart consume them. What I found was that my webpart sent the wrong data, but the list webpart worked as expected.

So I reflected the XsltListViewWebPart (or whatever it's exact name is) and I discovered that there is an IConnectionData interface. This allows you to specify the dependencies and get the correct delay binding you need. GetRequiresData indicates that there are still more connections to be consumed before the data can be requested.