on 08-02-2012 8:23 AM
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; }
Hi,I've sheared some code in other thread ( similar to this one) :
http://scn.sap.com/thread/3149160
Best regards,
Yarden
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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;
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
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;
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
87 | |
10 | |
10 | |
9 | |
7 | |
7 | |
6 | |
5 | |
4 | |
4 |
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.