I really do wish someone would create a real-world enterprise-class DataGrid for gtk# with Data Binding and many other fancy features.

And take this DataGrid and make it part of Gtk#.   Maybe have another gtk# assembly for these extra widgets.

Anyways, I have something I have worked on for awhile, maybe others can improve upon it and give back.  If someone is interested, we could put it into subversion somewhere with other gtk# widgets.  Chris and I have discussed this in the past, but there is only so much time.

Here are the source files I included:
DataGrid.cs - creates a DataGrid for Gtk# with data binding support.
TestDataGrid.cs - tests the gtk# data grid

Basically, you can take a pre-loaded DataTable, and then "data bind" it to the DataGrid.  It may not be true data binding like SWF or webforms, but its an attempt.

A change to the data in the DataGrid wi ll update the data in the DataTable.
If you add a row or delete a row in the DataGrid, it will be reflected in the DataTable.  If you modify a cell in the DataGrid, the row and column in the DataTable will be updated.

In the test, there are four menu items:
1. Add Row - adds a row
2. Dump Table - dumps to the console what's in the DataTable
3. Editable - sets the DataGrid editable or not
4. Delete Selected Row - deletes the highlighted row

One thing I would love to see added is an Input Mask and Format properties added to each column.   Let's say you would like to format dates as a short date, you would put "Short Date" in the format property for any locale.  Or you could set it to "MM/DD/YYYY" for US locale..   A numeric column you could have it format as "###,###,###.##" or just simply say "Currency" for any locale.
An input mask could limit certain characters, such as, alpha only, num eric only, alphanumeric.  Canadian postal code i believe is alpha, numeric, alpha, space, numeric, alpha, numeric.  So your input mask would be: "ANA NAN".

Anyways, please let me know if this is what you wanted.


Christian Hergert <[EMAIL PROTECTED]> wrote:
The original version of the datagrid i put in monodevelop was taken
from sqlsharpgtk. Daniel has since done some additions to the
monodevelop version to support basic editing and deletion. It also had
support for somewhat of a managed tree model. To be honest, im not
sure if ive merged that support yet. Both versions are a hack
regardless.

Your example below will not work. First, you cant add an object to a
gtk container that doesnt inherit from Gtk.Widget. Secondly, even if
it did work, you would have just doubled your requirements on every
platform to both gtk and swf.

-- Christian

On 11/17/05, Gennadiy Donchyts wrote:
> Hi all,
>
> I'm wondering if there is some DataGrid-like control available for
> Gtk# which has data-binding implemented. For now I've found 2
> DataGirds in the (1) sqlsharpgtk and (2) MD, which one of these is the
> latest and will be updated in the future?.
>
> Also there is implementation of the (3) SWF DataGrid ...quite complex
> and still in development but looks very nice also.
>
> The question is if will be theoretically possible to use SWF DataGrid instead of
> Gtk# controls, so to implement something like (Gtk <=> Swf bridge):
>
> using Swf = System.Windows.Forms;
>
> Swf.DataGrid grid = new Swf.DataGrid();
> Gtk.Window w = new Gtk.Window();
> window.Add(grid);
>
> Since I need everything to be cross- platform and stable for my application the
> Gtk# was chosen for gui development. After some play I managed to run a nice
> test (see below), but then it came to the point when it is necessary
> to extend it
> quite a lot (add events, properties, etc.) , so my second question is
> if someone is
> already doing or plan to continue development of that class?
>
> Best regards,
> --Gena
>
> -----------
> Test using SqlSharp DataGrid
> (NHibernate => IList => ObjectViews => (1, Gtk) DataGrid:
>
> ...
> class Project
> {
> private int id;
> private string name;
>
> public int ID { get ... }
> public string Name { get ... }
> }
> ...
>
> // load from db into IList using NHibernate
> IList projects = session.Select(typeof(Project), null);
>
> // create object view (ITypedList, IBindingList), see objectvi ews on sourceforge
> ObjevtView view = new ObjectView(typeof(Project));
> view.Columns.Add(new ObjectViewColumn("ID"));
> view.Columns.Add(new ObjectViewColumn("Name"));
> view.DataSource = projects;
>
> // create and fill project table
> DataGrid grid = new DataGrid();
> grid.DataSource = vew;
>
> which gives me a nice table with 2 columns :):
>
> ID Name
> -----------------
> 1 project1
> 2 project2
> _______________________________________________
> Gtk-sharp-list maillist - [email protected]
> http://lists.ximian.com/mailman/listinfo/gtk-sharp-list
>


--
Christian Hergert
Medsphere Systems Corporation
Software Programmer
C: 253 906 2115
_______________________________________________
Gtk-sharp-list maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/gtk-sharp-list


Yahoo! FareChase - Search multiple travel sites in one click.
// DataGrid.cs
namespace Mono.Data.GtkSharp
{
        // notice System.Data is not references here

        using System;
        using System.Collections;
        using System.ComponentModel;
        using System.Reflection;
        using System.Runtime.InteropServices;
        using System.Text;
        
        using GLib;
        using Gtk;

        public class DataGridColumn 
        {
                private string columnName = "";
                private TreeViewColumn treeViewColumn = null;
                public CellRendererText Renderer = null; // should be internal

                public string ColumnName {
                        get {
                                return columnName;
                        }
                        set {
                                columnName = value;
                        }
                }

                public TreeViewColumn TreeViewColumn {
                        get {
                                return treeViewColumn;
                        }
                        set {
                                treeViewColumn = value;
                        }
                }
        }

        public class DataGrid : VBox {
                private ListStore store;
                private TreeView treeView;

                public ArrayList gridColumns; // TODO: make Columns a collection

                public DataGrid () : base(false, 4) {           
                        ScrolledWindow sw = new ScrolledWindow ();
                        this.PackStart (sw, true, true, 0);

                        treeView = new TreeView (store);
                        treeView.HeadersVisible = true;
                        //treeView.ModifyFont (Pango.FontDescription.FromString 
("courier new"));

                        gridColumns = new ArrayList(0);

                        sw.Add (treeView);

                        store = new ListStore (GLib.GType.String);

                        treeView.EnableSearch = true;
                        treeView.HeadersClickable = true;
                        dataMember = "";
                        dataSource = null;
                        
                        
                }

                ArrayList bindrows = null;
                object resolvedDataSource = null;

                private bool editable = true;

                private object dataSource;

                private string dataMember;

                public int SelectedRow { 
                        get {
                                TreeIter iter;
                                TreeModel model;
                                TreeSelection selection = treeView.Selection;
                                if (selection.GetSelected (out model, out 
iter)) {
                                        TreePath[] path = 
selection.GetSelectedRows (out model);
                                        return path[0].Indices[0]; // return 
selected row 
                                }
                                else
                                        return -1; // not selected
                        }
                }

                public TreeIter SelectedIter {
                        get {
                                TreeIter iter;
                                TreeModel model;
                                TreeSelection selection = treeView.Selection;
                                if (selection.GetSelected (out model, out iter))
                                        return iter; // return seelcted iter
                                else
                                        return TreeIter.Zero; // not selected
                        }

                }

                public TreeView View 
                {
                        get 
                        {
                                return treeView;
                        }
                }

                public object DataSource 
                {
                        get 
                        {
                                return dataSource;
                        }
                        set 
                        {
                                dataSource = value;
                        }
                }

                public string DataMember 
                {
                        get 
                        {
                                return dataMember;
                        }
                        set 
                        {
                                dataMember = value;
                        }
                }

                public ListStore Store 
                {
                        get 
                        {
                                return store;
                        }
                }

                public ArrayList Columns 
                {
                        get 
                        {
                                return gridColumns;
                        }
                }

                public bool Editable {
                        get {
                                return editable; // not a good way to see if 
its editable or not 
                                // because various columns could be editable 
and others non-editable
                        }

                        set {
                                editable = value;
                                if (value == true) {
                                        for(int c = 0; c < gridColumns.Count; 
c++) {
                                                DataGridColumn col = 
(DataGridColumn) gridColumns[c];
                                                col.TreeViewColumn.Clickable = 
true;
                                                col.Renderer.Mode = 
CellRendererMode.Editable;
                                                col.Renderer.Editable = true;
                                        }
                                        treeView.RulesHint = true;
                                        treeView.Selection.Mode = 
SelectionMode.Single;
                                }
                                else {
                                        for(int c = 0; c < gridColumns.Count; 
c++) {
                                                DataGridColumn col = 
(DataGridColumn) gridColumns[c];
                                                col.TreeViewColumn.Clickable = 
false;
                                                col.Renderer.Mode = 
CellRendererMode.Inert;
                                                col.Renderer.Editable = false;
                                        }
                                        treeView.RulesHint = false;
                                        treeView.Selection.Mode = 
SelectionMode.Single;
                                }
                        }
                }

                public int AddNew() 
                {
                        // TODO: need to check if resolved data source is not 
null

                        IBindingList b = (IBindingList) resolvedDataSource;

                        if (b.AllowNew) {
                                object obj = b.AddNew();
                                if (obj == null) {
                                        //Console.Error.WriteLine("obj is 
null");
                                }
                                else {
                                        //Console.Error.WriteLine("Type: " + 
obj.GetType().ToString());
                                        bindrows.Add(obj);

                                        TreeIter iter = NewRow();               
        
                                        for(int i = 0; i < gridColumns.Count; 
i++)
                                                SetColumnValue (iter, i, 
String.Empty);

                                        return bindrows.Count - 1;
                                }
                        }

                        return -1;
                }

                public int DeleteRow(int row) 
                {
                        if (row < 0)
                                return -1; // should throw an exception - out 
of range

                        TreeIter iter = TreeIter.Zero;
                        if (store.IterNthChild(out iter, row) == false)
                                return -1;

                        IBindingList b = (IBindingList) resolvedDataSource;
                        if (b.AllowRemove) {
                                IList list = (IList) resolvedDataSource;
                                bindrows.RemoveAt(row);
                                store.Remove (ref iter);
                                list.RemoveAt (row);

                                return row;
                        }

                        return -1;
                }

                // sets the column count.  beware, it clears
                // use this if you are going to load each column and row 
yourself
                // instead of using DataBind() or DataLoad()
                public void SetColumnCount (int columnCount) 
                {
                        Clear ();
                        dataMember = "";
                        dataSource = null;

                        GLib.GType[] theTypes = new GLib.GType[columnCount];
                        gridColumns = new ArrayList ();
                        for (int col = 0; col < columnCount; col++) 
                        {
                                theTypes[col] = GLib.GType.String;
                                gridColumns.Add (new DataGridColumn ());
                        }
                        store.ColumnTypes = theTypes;
                }

                // load data from a data table or data set
                public long DataBind () 
                {
                        long rowsRetrieved = 0;

                        Clear ();

                        System.Object o = null;
                        o = GetResolvedDataSource (DataSource, DataMember);
                        resolvedDataSource = o;
                        IEnumerable ie = (IEnumerable) o;
                        ITypedList tlist = (ITypedList) o;
                        TreeIter iter = new TreeIter ();
                                                                        
                        PropertyDescriptorCollection pdc = 
tlist.GetItemProperties (new PropertyDescriptor[0]);
                        gridColumns = new ArrayList(pdc.Count);

                        // define the columns in the treeview store
                        // based on the schema of the result
                        GLib.GType[] theTypes = new GLib.GType[pdc.Count];
                        for (int col = 0; col < pdc.Count; col++) {
                                theTypes[col] = GLib.GType.String;
                        }
                        store.ColumnTypes = theTypes;

                        bindrows = new ArrayList();

                        int colndx = -1;
                        foreach (PropertyDescriptor pd in pdc) {

                                colndx ++;

                                DataGridColumn gridCol = new DataGridColumn ();
                                gridCol.ColumnName = pd.Name;           
                                gridColumns.Add (gridCol);
                        }

                        bindrows = new ArrayList();

                        foreach (System.Object obj in ie) {
                                ICustomTypeDescriptor custom = 
(ICustomTypeDescriptor) obj;
                                PropertyDescriptorCollection properties = 
custom.GetProperties ();

                                bindrows.Add(obj);
                                
                                rowsRetrieved ++;
                                iter = NewRow ();
                                int cv = 0;
                                foreach (PropertyDescriptor property in 
properties) {
                                        object oPropValue = property.GetValue 
(obj);
                                        string sPropValue = "";
                                        if (oPropValue.GetType ().ToString 
().Equals("System.Byte[]"))  {
                                                //sPropValue = 
SqlSharpGtk.GetHexString ((byte[]) oPropValue);
                                                Console.Error.WriteLine("Byte[] 
 value");
                                        }
                                        else
                                                sPropValue = 
oPropValue.ToString ();
                                                                                
                                        SetColumnValue (iter, cv, sPropValue);
                                        cv++;                   
                                }
                        }

                        treeView.Model = store;
                        AutoCreateTreeViewColumns ();
                        return rowsRetrieved;
                }

                // borrowed from Mono's System.Web implementation
                protected IEnumerable GetResolvedDataSource(object source, 
string member) 
                {
                        if (source != null && source is IListSource) {
                                IListSource src = (IListSource) source;
                                IList list = src.GetList ();
                                if (!src.ContainsListCollection) {
                                        return list;
                                }
                                if (list != null && list is ITypedList) {

                                        ITypedList tlist = (ITypedList) list;
                                        PropertyDescriptorCollection pdc = 
tlist.GetItemProperties (new PropertyDescriptor[0]);
                                        if (pdc != null && pdc.Count > 0) {
                                                PropertyDescriptor pd = null;
                                                if (member != null && 
member.Length > 0) {
                                                        pd = pdc.Find (member, 
true);
                                                } else {
                                                        pd = pdc[0];
                                                }
                                                if (pd != null) {
                                                        object rv = pd.GetValue 
(list[0]);
                                                        if (rv != null && rv is 
IEnumerable) {
                                                                return 
(IEnumerable)rv;
                                                        }
                                                }
                                                throw new Exception 
("ListSource_Missing_DataMember");
                                        }
                                        throw new Exception 
("ListSource_Without_DataMembers");
                                }
                        }
                        if (source is IEnumerable) {
                                return (IEnumerable)source;
                        }
                        return null;
                }

                public void Clear () 
                {
                        if (store != null) 
                        {
                                store.Clear ();
                                store = null;
                                store = new ListStore (GLib.GType.String);
                        }
                        else
                                store = new ListStore (GLib.GType.String);

                        if (gridColumns != null) 
                        {
                                for (int c = 0; c < gridColumns.Count; c++) 
                                {
                                        DataGridColumn gridCol = 
(DataGridColumn) gridColumns[c];
                                        if (gridCol.TreeViewColumn != null) 
                                        {
                                                treeView.RemoveColumn 
(gridCol.TreeViewColumn);
                                                gridCol.TreeViewColumn = null;
                                        }
                                }
                                gridColumns.Clear ();
                                gridColumns = null;
                        }
                }

                public TreeIter NewRow () 
                { 
                        return store.Append();
                }

                public void AddRow (object[] columnValues) 
                {       
                        TreeIter iter = NewRow ();                      
                        for(int col = 0; col < columnValues.Length; col++) {
                                string cellValue = columnValues[col].ToString 
();
                                SetColumnValue (iter, col, cellValue);
                        }
                }

                public void SetColumnValue (TreeIter iter, int column, string 
value) 
                {
                        GLib.Value cell = new GLib.Value (value);
                        store.SetValue (iter, column, cell);    
                }

                public void SetColumnValue (TreeIter iter, int column, byte[] 
value) 
                {
                        //string svalue = SqlSharpGtk.GetHexString (value);
                        //SetColumnValue (iter, column, svalue);
                }

                private void AutoCreateTreeViewColumns () 
                {
                        for(int col = 0; col < gridColumns.Count; col++) {
                                // escape underscore _ because it is used
                                // as the underline in menus and labels
                                StringBuilder name = new StringBuilder ();
                                foreach (char ch in ((DataGridColumn) 
gridColumns[col]).ColumnName) {
                                        if (ch == '_')
                                                name.Append ("__");
                                        else
                                                name.Append (ch);
                                }
                                TreeViewColumn tvc = CreateColumn (col, 
name.ToString ());
                                AppendColumn (tvc);
                        }
                }

                public int AppendColumn(TreeViewColumn tvc) 
                {
                        return treeView.AppendColumn (tvc);
                }

                private void TextCellEdited (object o, EditedArgs args) 
                {
                        IBindingList b = (IBindingList) resolvedDataSource;
                        if (b.AllowEdit) {
                                // ITypedList may help you figure out how to 
convert
                                // between different data types
                                // such as, how to display numbers, dates, 
etc...

                                TreePath path = new TreePath (args.Path);
                                TreeIter iter;
                                store.GetIter (out iter, path);
                                int i = path.Indices[0];
                        
                                TreePath cpath;
                                string cellValue = args.NewText;

                                TreeViewColumn tvcolumn;
                                treeView.GetCursor (out cpath, out tvcolumn);
                                int c = 0;
                                for(c = 0; c < gridColumns.Count; c++) {
                                        TreeViewColumn tvc = ((DataGridColumn) 
gridColumns[c]).TreeViewColumn;
                                        if (tvcolumn == tvc) {
                                                Console.Error.WriteLine("Column 
clicked:  Column Name: " + tvcolumn.Title);
                                                Console.Error.WriteLine("     
Ordinal: " + c.ToString());
                                                break;
                                        }
                                }

                                if (c >= gridColumns.Count)
                                        Console.Error.WriteLine("tv col not 
found");

                                ICustomTypeDescriptor custom = 
(ICustomTypeDescriptor) bindrows[i];
                                PropertyDescriptorCollection properties = 
custom.GetProperties ();
                                PropertyDescriptor pd = properties[c];
                                pd.SetValue(bindrows[i], cellValue);
                        
                                Console.Error.WriteLine("    Row number: " + 
path.Indices[0].ToString());
                                Console.Error.WriteLine("    Cell Value: " + 
cellValue);
                        
                                ((IEditableObject) bindrows[i]).BeginEdit();
                                SetColumnValue(iter, c, cellValue);
                                ((IEditableObject) bindrows[i]).EndEdit();
                        }
                }

                public TreeViewColumn CreateColumn (int columnNum, string 
columnName) 
                {
                        TreeViewColumn treeViewCol = new TreeViewColumn ();     
         
                        CellRendererText renderer = new CellRendererText ();
                        treeViewCol.Clickable = true;
                        treeView.RulesHint = true;
                        
                        treeView.Selection.Mode = SelectionMode.Single;
                        //treeView.Selection.Mode = SelectionMode.Multiple;

                        // Editable, Activatable, Inert
                        renderer.Mode = CellRendererMode.Editable;
                        //renderer.Family = "courier new";
                        renderer.Editable = true;
                        renderer.Edited += new EditedHandler (TextCellEdited);
                        treeViewCol.Title = columnName;
                        treeViewCol.PackStart (renderer, true);
                        treeViewCol.AddAttribute (renderer, "text", columnNum);

                        DataGridColumn gridCol = (DataGridColumn) 
gridColumns[columnNum];
                        gridCol.Renderer = renderer;
                        gridCol.TreeViewColumn = treeViewCol;
                        
                        return treeViewCol;
                }
        }
}

// $ mcs /out:TestDataGrid.exe TestDataGrid.cs DataGrid.cs -pkg:gtk-sharp-2.0 
/r:System.Data.dll
// TestDataGrid.cs
namespace Mono.Data.GtkSharp 
{
        using System;
        using System.Collections;
        using System.Collections.Specialized;
        using System.Configuration;
        using System.Data;
        using System.Data.Common;
        using System.Data.SqlTypes;
        using System.Text;
        using System.IO;
        using System.Reflection;
        using System.Runtime.Remoting;
        using System.Runtime.InteropServices;
        using System.Diagnostics;

        using Gdk;
        using Gtk;

        public class TestDataGrid 
        {
                private DataTable table;
                private Gtk.Window win;
                private DataGrid grid;
                //private TextView textView;

                public static readonly string ApplicationName = "Gtk# DataGrid 
Test";   

                public TestDataGrid () 
                {
                        CreateGui ();
                }

                public DataGrid Grid {
                        get {
                                return grid;
                        }
                }

                public void Show () 
                {
                        win.ShowAll ();
                }

                public void CreateGui () 
                {
                        win = new Gtk.Window (ApplicationName);
                        win.DeleteEvent += new Gtk.DeleteEventHandler 
(OnWindow_Delete);
                        win.BorderWidth = 4;
                        win.SetDefaultSize (600, 500);
                        
                        VBox vbox = new VBox (false, 4);
                        win.Add (vbox);

                        MenuBar mb = CreateMenuBar ();
                        vbox.PackStart (mb, false, false, 0);
                        
                        VPaned vpaned = new VPaned ();
                        vbox.PackStart (vpaned, true, true, 0);
                        grid = CreateOutputResultsDataGrid();
                        vpaned.Add1 (grid);
                }

                DataGrid CreateOutputResultsDataGrid () 
                {
                        DataGrid grid = new DataGrid ();

                        //grid.View.ButtonReleaseEvent +=
                        //      new Gtk.ButtonReleaseEventHandler 
(OnDataGridButtonRelease);
                        //grid.Editable = false;

                        return grid;
                }

                void OnWindow_Delete (object o, Gtk.DeleteEventArgs args) 
                {
                        QuitApplication();
                }

                void QuitApplication () 
                {
                        Application.Quit ();
                }

                public static void DoEvents () 
                {
                        while (Application.EventsPending ()) 
                                Application.RunIteration ();
                }

                public DataTable BuildDataTableSample() 
                {
                        table = new DataTable();

                        int maxColumns = 5;
                        int maxRows = 3;

                        for(int i = 0; i < maxColumns; i++) {
                                string columnName = String.Format("Column{0}", 
i);
                                table.Columns.Add(columnName);
                        }
                        
                        for(int r = 0; r < maxRows; r++) {
                                DataRow row = table.NewRow();
                                for(int c = 0; c < table.Columns.Count; c++) {
                                        string cellValue = 
String.Format("(Row{0},Column{1})", r, c);
                                        row[c] = cellValue;
                                }
                                table.Rows.Add(row);
                        }

                        return table;
                }

                void OnMenu_DumpTable (object o, EventArgs args) 
                {
                        Console.Error.WriteLine("__===========  T a b l e     D 
u m p  =========__");
                        Console.Error.WriteLine("Row Count: " + 
table.Rows.Count.ToString());
                        for(int r = 0; r < table.Rows.Count; r++) {
                                DataRow row = table.Rows[r];
                                StringBuilder sb = new StringBuilder();
                                for(int c = 0; c < table.Columns.Count; c++) {
                                        string s = row[c].ToString();
                                        sb.Append(s);
                                        sb.Append(" ");
                                }
                                Console.Error.WriteLine(sb.ToString());
                        }
                        
Console.Error.WriteLine("=-----------------------------------------------=");
                }

                void OnMenu_Editable (object o, EventArgs args) 
                {
                        grid.Editable = !grid.Editable;
                }

                void OnMenu_AddNew (object o, EventArgs args) 
                {
                        AddNew();
                }

                void OnMenu_DeleteSelectedRow (object o, EventArgs args) 
                {
                        int selectedRow = 0;
                        selectedRow = grid.SelectedRow;
                        if (selectedRow >= 0)
                                grid.DeleteRow (selectedRow);
                }

                void AddNew() 
                {
                        grid.AddNew();
                }

                public MenuBar CreateMenuBar () {
                        MenuBar menuBar = new MenuBar ();
                        Menu menu;
                        MenuItem item;
                        MenuItem barItem;

                        menu = new Menu ();

                        item = new MenuItem ("Add Row");
                        item.Activated += new EventHandler (OnMenu_AddNew);
                        menu.Append (item);

                        item = new MenuItem ("Dump Table");
                        item.Activated += new EventHandler (OnMenu_DumpTable);
                        menu.Append (item);

                        item = new MenuItem ("Editable");
                        item.Activated += new EventHandler (OnMenu_Editable);
                        menu.Append (item);

                        item = new MenuItem ("Delete Selected Row");
                        item.Activated += new EventHandler 
(OnMenu_DeleteSelectedRow);
                        menu.Append (item);

                        barItem = new MenuItem ("Test");
                        barItem.Submenu = menu;
                        menuBar.Append (barItem);

                        return menuBar;
                }

                public static int Main (string[] args) 
                {
                        Application.Init ();
                        TestDataGrid test = new TestDataGrid ();
                        DataTable sampleTable = test.BuildDataTableSample();
                        test.Grid.DataSource = sampleTable;
                        test.Grid.DataBind();
                        test.Show ();
                        DoEvents ();
                        //test.Grid.Editable = false;
                        Application.Run ();
                        return 0;
                }
        }
}

_______________________________________________
Gtk-sharp-list maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/gtk-sharp-list
  • [Gtk-sharp-l... Gennadiy Donchyts
    • Re: [Gt... Christian Hergert
      • Re:... Gennadiy Donchyts
      • Re:... Daniel Morgan
        • ... Gennadiy Donchyts
          • ... Victor Rafael Rivarola Soerensen (FANATICO y LOCO por Cristo)
            • ... Gennadiy Donchyts
            • ... Gennadiy Donchyts
              • ... Victor Rafael Rivarola Soerensen (FANATICO y LOCO por Cristo)
                • ... Gennadiy Donchyts
                • ... Scott Ellington
                • ... Gennadiy Donchyts
                • ... Victor Rafael Rivarola Soerensen (FANATICO y LOCO por Cristo)
                • ... Gennadiy Donchyts

Reply via email to