4 Replies Latest reply on May 16, 2018 3:30 PM by Rick Davin

    Creating a Pi Point using a Winform


      Hi ,


      I have created a winform and would  like to do something similar like below.

      Where the user chooses the point class, point type from a combobox and depending on what values it populates the values in the datagridview are changed.

      What is the correct call to make the datagridview populate with pi point attributes?



        • Re: Creating a Pi Point using a Winform

          PICommonPointAttributes Class contains information about common PIPoint attributes. The actual attribute names defined by the PIPointClass for a PIServer can be obtained using the GetAttributes() method.

            • Re: Creating a Pi Point using a Winform
              Rick Davin

              Using the PIServer.PointClasses property, you get the point classes for a given PI Data Archive.  This could also be used to populate the combo box for the same.


              Then as Thyagarajan Ramachandran said, you would use the PIPointClass.GetAttributes method to get a dictionary of attributes and their associated default settings.  This differs from the PIPoint.GetAttributes method, which brings along current settings for the specified PIPoint.


              The resulting dictionary can be assigned as the DataGridView.DataSource.  I would recommend using an intermediary BindingSource, and set the BindingSource.DataSource to be the dictionary from GetAttributes, and the DataGridView.DataSource would be the BindingSource.


              As for enabling or disabling given rows associated with a PIPoint attribute, that may be done by detecting the PIPointType.  For instance, a digital tag would want the row for DigitalSetName enabled, whereas it would be disabled for other rows.  This is up to you to code per row.


              As for having the value column support an internal combo box or other feature, that is beyond the topic of PI Developer Technologies.  I would refer you to MSDN or other forums such as StackOverflow.

              2 of 2 people found this helpful
                • Re: Creating a Pi Point using a Winform
                  Dan Fishman

                  I am not sure if it is a good idea to set the Bindsource.DataSource to a dictionary, although I haven't tried it.  I have seen on stackoverflow issues because dictionaries do not implement IList and DataSource expects an IList.

                    • Re: Creating a Pi Point using a Winform
                      Rick Davin

                      Right you are, Dan Fishman.  Thanks for keeping me honest!


                      Okay Alan, first add the following class to your project.


                          public class NameValuePair
                              public string Name { get; set; }
                              public object Value { get; set; }
                              public static IList<NameValuePair> ConvertToList(IDictionary<string, object> dict)
                                  List<NameValuePair> list = new List<NameValuePair>();
                                  foreach (KeyValuePair<string, object> entry in dict)
                                      NameValuePair item = new NameValuePair { Name = entry.Key, Value = entry.Value };
                                  return list;


                      It's basically a Name and Value, but does have a method to convert a dictionary to a list.  Next, rebuild your project.  This is required so that NameValuePair class is available later as a data source.


                      Add a binding source to your WinForm.  Let's say it's named "bindingSource1".  Thanks to the previous build (or rebuild), you may declare NameValuePair as bindingSource1.DataSource while in design mode.  While still in design mode you set the data grid view's DataSource equal to bindingSource1.  Later in run mode, you will dynamically change bindingSource1.DataSource to be a List<NameValuePair> but that's okay because the metadata hasn't changed (that is to say the expected grid columns are still expecting the properties of the NameValuePair class).  Feel free to review and modify the code below:


                          private PIServer DataServer => new PIServers().DefaultPIServer;
                          private PIPointClass PointClass => cbxPointClass.SelectedIndex < 0 ? null : (PIPointClass)cbxPointClass.SelectedValue;
                          private PIPointType PointType => cbxPointType.SelectedIndex < 0 ? PIPointType.Null : (PIPointType)cbxPointType.SelectedValue;
                          private IList<NameValuePair> ClassDefaultAttributes => NameValuePair.ConvertToList(PointClass?.GetAttributes());
                          public Form1()
                              cbxPointClass.DataSource = DataServer.PointClasses;
                              cbxPointType.DataSource = Enum.GetValues(typeof(PIPointType)).Cast<PIPointType>();
                          private void cbxPointClass_SelectedIndexChanged(object sender, EventArgs e)
                              bindingSource1.DataSource = ClassDefaultAttributes;


                      Anytime the selected PointClass is changed in the combo box (cbxPointClass), bindingSource1 gets a new DataSource (line 16).  When Form1 is created, the 2 combo boxes are populated easily (lines 10 & 11) and each will automatically select the first item in the collection.


                      Here's a very quick layout:


                      2018-05-16 07_31_23-Example PIPoint Attributes.png


                      You may change the heading of the DGV columns or whatever customization you prefer.  Really after this point, there is nothing to do with PI Developer Technologies and is more about WinForm and .NET.  Again, there are better resources for those topics (MSDN, StackOverflow, Google).

                      1 of 1 people found this helpful