cancel
Showing results for 
Search instead for 
Did you mean: 

WPF Datagrid binding

phil_soady
Participant
0 Kudos

The sample file and Docu show binding RFC Table to a Windows Form DataGridView.

That works.

What about a WPF Datagrid.   Or better said a nice implementation of a DataSource so it can be bound to ANY WPF control.

After trying

MyControl.ItemsSource = ((ISupportTableView) MyRfcTable).DefaultView;

or

Mycontrol.ItemsSource = (IBindingListView)((ISupportTableView)MyRfcTable).DefaultView;

The result is a grid with 3 fields.  ROW, TableView , IsEdit

it would appear that a valid DataSource is not being prepared.

The correct number of rows are recognised. But it seems to fail on the column aspect passing some control info and not the actual data.

Has anyone got RFCTable to bind to a WPF control ? VB or C# code

Message was edited by: Phil Soady BTW, Something like the following works. But involves creating types.  Ie expected .net connector to make these types dynamically available The LIST<T> or the real type not the RFCStructure would be good. has someone built the Dynamic Type generation for this already ? mycontrol.Itemssource = GetBla(mytab);          public class BLA        {             public string F1 { get; set; }             public string F2  { get; set; }             public string F3 { get; set; }             public string F4 { get; set; }         }         public static List<BLA>  GetBLA( IRfcTable mytab)         {            var _tBLA = new List<BLA>();             foreach (var stru in mytab)             {                 var _bla = new BLA();                _bla.F1 = stru.GetString("FIELD1");                _bla.F2 = stru.GetString("FIELD2");                _bla.F3 = stru.GetString("FIELD3");                 _tBLA.Add(_bla);             }             return _tBLA;         }

Accepted Solutions (1)

Accepted Solutions (1)

Former Member
0 Kudos

Hi,I've sheared some code in other thread ( similar to this one) :

http://scn.sap.com/thread/3149160

Best regards,

Yarden

Answers (2)

Answers (2)

phil_soady
Participant
0 Kudos

Thanks Case, thanks Yarden.

For the record, as no doubt in the future some poor soul will google why the IRfcTable is so nasty.

The result i think works best is:   But there are other options.... This is an EXAMPLE solution. 

WPF Window. (XAML)

  <DataGrid Name="DataGridServiceRegistry"  AutoGenerateColumns="True" Height="Auto" Width="Auto" VerticalAlignment="Bottom" HorizontalAlignment="Right" />

Then in the Code behind.

// logon to SAP   see sample SNC logon below

//

using SAP.Middleware.Connector;

using System.Data;

private IRfcTable _SRBrowser;

SBTB1.Text = SAPnco_Fascade.LogonTtoSAP() ? "Connected..." : "Connection failed...";      // logon to sap, boolean result

_SRBrowser = SAPnco_Fascade.Loadregistry();        "// call an SAP function and return an IRfcTable object

DataTable dt = _SRBrowser.GetDataTable();            "' use the extension method that converts an IRFCTable to a DataTable

// now bind our hard won data to the control...

DataGridServiceRegistry.ItemsSource = dt.DefaultView;    "// after try, tolist() and other options, this is the one I like.

...

...

public static IRfcTable Loadregistry()

        {

          // this isnt the only way to call functions,,,, I have been looking at managing STATE... hence use of sessions...

          // See teh SAPNCO docu for more examples  i have included a reproduced Func call sample for SAP DOCU at the bottom here FYI

            IRfcFunction func = _dest.Repository.CreateFunction("BAPI...RFC...BLA");

            RfcSessionManager.BeginContext(_dest);

            func.Invoke(_dest);

            RfcSessionManager.EndContext(_dest);

            IRfcTable SRBrowser = func.GetTable("ITABNAME_AS_PER_FUNC");

            return SRBrowser;

          

          

  

        }

// Extension method GetDataTable to sap IRFC TABLES.   // Courtesy of Yarden jacobsen

public static class SapToDataExtensionClass

    {

        public static DataTable GetDataTable(this IRfcTable i_Table)

        {

            DataTable dt = new DataTable();

            dt.GetColumnsFromSapTable(i_Table);

            dt.FillRowsFromSapTable(i_Table);

            return dt;

        }

        public static void FillRowsFromSapTable(this DataTable i_DataTable, IRfcTable i_Table)

        {

            foreach (IRfcStructure tableRow in i_Table)

            {

                DataRow dr = i_DataTable.NewRow();

                dr.ItemArray = tableRow.Select(structField => structField.GetValue()).ToArray();

                i_DataTable.Rows.Add(dr);

            }

        }

        public static void GetColumnsFromSapTable(this DataTable i_DataTable, IRfcTable i_SapTable)

        {

            var DataColumnsArr = i_SapTable.Metadata.LineType.CreateStructure().ToList().Select

            (structField => new DataColumn(structField.Metadata.Name)).ToArray();

            i_DataTable.Columns.AddRange(DataColumnsArr);

        }

    }

namespace mydemo{

    public class SAPnco_Fascade

    {

        private static RfcDestination _dest;

   

        public static bool LogonToSAP()

        {

            

            var parms = new RfcConfigParameters();

            parms.Clear();

            parms.Add(RfcConfigParameters.Name, "PRDSNC");

            parms.Add(RfcConfigParameters.SncMode, "1");

            parms.Add(RfcConfigParameters.SncPartnerName, "p:host/xxxx@yoursncdetails");

            parms.Add(RfcConfigParameters.SncQOP, "9"); // max security under SNC option... yes 9

            parms.Add(RfcConfigParameters.Client, "100");

            parms.Add(RfcConfigParameters.Language, "EN");

            parms.Add(RfcConfigParameters.MessageServerHost, "10.xxx.xxx.xxx");

            parms.Add(RfcConfigParameters.SystemID, "PRD");

            parms.Add(RfcConfigParameters.LogonGroup, "DEFAULT");

            parms.Add(RfcConfigParameters.UseSAPGui, "0");  // 1 allows sapgui use

            _dest = RfcDestinationManager.GetDestination(parms);

            if (_dest != null)

                return true;    // only error checking below.

}

}

static IRfcTable GetTableByRfcCall(string destName, int rowCount)

{

// get the destination

RfcDestination dest = RfcDestinationManager.GetDestination(destName);

// create a function object

IRfcFunction func = dest.Repository.CreateFunction("STFC_STRUCTURE");

//prepare input parameters

IRfcStructure impStruct = func.GetStructure("IMPORTSTRUCT");

impStruct.SetValue("RFCFLOAT", 12345.6789);

impStruct.SetValue("RFCCHAR1", "A");

impStruct.SetValue("RFCCHAR2", "AB");

impStruct.SetValue("RFCCHAR4", "NCO3");

impStruct.SetValue("RFCINT4", 12345);

impStruct.SetValue("RFCHEX3", new byte[] { 0x41, 0x42, 0x43 });

impStruct.SetValue("RFCDATE", DateTime.Today.ToString("yyyy-MM-dd"));

impStruct.SetValue("RFCDATA1", "Hello World");

// fill the table parameter

IRfcTable rfcTable = func.GetTable("RFCTABLE");

for (int i = 0; i < rowCount; i++)

{

// make a copy of impStruct

IRfcStructure row = (IRfcStructure)impStruct.Clone();

// make such changes to the fields of the cloned structure

impStruct.SetValue("RFCFLOAT", 12345.6789 + i);

row.SetValue("RFCINT1", i);

row.SetValue("RFCINT2", i * 2);

row.SetValue("RFCINT4", i * 4);

impStruct.SetValue("RFCTIME", DateTime.Now.ToString("T"));

row.SetValue("RFCDATA1", i.ToString() + row.GetString("RFCDATA1"));

rfcTable.Append(row);

}

// submit the RFC call

func.Invoke(dest);

// Return the table. The backend has added one more line to it.

rfcTable = func.GetTable("RFCTABLE");

return rfcTable;

}

former_member197445
Contributor
0 Kudos

Try this.  I have a function that converts the IRfcTable to a DataTable.  Since WPF needs an IEnumerable for the ItemsSource, you might be able to use DefaultView of the DataTable.  Or if not that then try dataTable.Select().ToList().

public static DataTable GetDataTableFromRFCTable(IRfcTable functionRfcTable)

{

          DataTable data = new DataTable();

          //Create data table.

          for (int i = 0; i <= functionRfcTable.ElementCount - 1; i++) {

                    RfcElementMetadata metadata = functionRfcTable.GetElementMetadata(i);

                    data.Columns.Add(metadata.Name);

          }

          //Transfer rows from rfcTable to .Net table.

          foreach (IRfcStructure row in functionRfcTable) {

                    DataRow rowAdd = data.NewRow();

                    for (int j = 0; j <= functionRfcTable.ElementCount - 1; j++) {

                              RfcElementMetadata metadata = functionRfcTable.GetElementMetadata(j);

                              rowAdd[metadata.Name] = row.GetString(metadata.Name);

                    }

                    data.Rows.Add(rowAdd);

          }

          return data;

}