0

非常感谢 Jonathan Peppers 关于如何刷新 tableview 的建议。


更新:这是我的解决方案的链接:https ://github.com/Videlia/Veggies.git 。此外,我发现,一旦我在横向视图中添加了 5 个项目,或者在纵向视图中添加了大约 7 或 8 个项目,列表就会重新开始显示顶部项目,而不是继续向下显示列表。但是,如果我选择一行,它会选择应该显示的值。

如果我添加或编辑一行(这两者都需要我转到另一个屏幕然后返回到这个屏幕),我的 tableview 现在可以正常工作。由于某种原因,在同一屏幕上执行的删除操作不会重新加载数据。

这是我更新的代码:

视图控制器

using System;
using System.Drawing;

using MonoTouch.Foundation;
using MonoTouch.UIKit;

namespace TableViewTest
{
public partial class vc_ManageVeggies : UIViewController
{
    public vc_ManageVeggies () : base ("vc_ManageVeggies", null)
    {
    }

    public override void DidReceiveMemoryWarning ()
    {
        // Releases the view if it doesn't have a superview.
        base.DidReceiveMemoryWarning ();

        // Release any cached data, images, etc that aren't in use.
    }

    public override void ViewDidLoad ()
    {
        base.ViewDidLoad ();

        // connect table to source.
        VeggieTableSource source = new VeggieTableSource ();

        Console.WriteLine ("\n vc_ManageVeggies.ViewDidLoad: " + Veggies.CountVeggies ().ToString () + " veggies found! :-)");

        if (Veggies.CountVeggies () > 0) {

            this.tblVeggies.Source = source;
        }

        btnNewVeggie.TouchUpInside += delegate {

            Veggies.SelectedVeggie = string.Empty;

            vc_VeggieAddEdit newScreen = new vc_VeggieAddEdit ();
            try {
                this.NavigationController.PushViewController (newScreen, false);
            } catch (Exception ex) {
                Console.WriteLine ("btnNewVeggie error: " + ex.ToString ());
            }
        };


        btnEditVeggie.TouchUpInside += delegate {

            if (Veggies.SelectedVeggie == string.Empty) {
                UIAlertView alert = new UIAlertView ("Oops!", "Please select a veggie to edit.", null, "OK");
                alert.Show ();
            } else {
                vc_VeggieAddEdit newScreen = new vc_VeggieAddEdit ();
                this.NavigationController.PushViewController (newScreen, false);
            }
        };


        btnDeleteVeggie.TouchUpInside += delegate {

            Veggies.DeleteVeggie (Veggies.SelectedVeggie);

            // update VeggieNames list and reload tableview data.
            //Veggies.RefreshVeggieList ();
            Veggies.VeggieNames.Remove (Veggies.SelectedVeggie);
            tblVeggies.ReloadData ();

        };

        btnDone.TouchUpInside += delegate {

            vc_MainMenu newScreen = new vc_MainMenu ();
            NavigationController.PushViewController (newScreen, false);
        };

    }

    public override void ViewDidUnload ()
    {
        base.ViewDidUnload ();

        // Clear any references to subviews of the main view in order to
        // allow the Garbage Collector to collect them sooner.
        //
        // e.g. myOutlet.Dispose (); myOutlet = null;

        ReleaseDesignerOutlets ();
    }

    public override bool ShouldAutorotateToInterfaceOrientation (UIInterfaceOrientation toInterfaceOrientation)
    {
        // Return true for supported orientations
        return (toInterfaceOrientation != UIInterfaceOrientation.PortraitUpsideDown);
    }

    public void RefreshVeggieTable ()
    {



    }
}
}

表源 使用系统;使用 MonoTouch.UIKit;使用 MonoTouch.Foundation;使用 System.Collections.Generic;

namespace TableViewTest
{
public class VeggieTableSource: UITableViewSource
{
    //List<string> veggieNames;

    public VeggieTableSource ()
    {
        Veggies.GetVeggieNames ();
    }

            #region implemented abstract members of MonoTouch.UIKit.UITableViewSource
    public override int RowsInSection (UITableView tableview, int section)
    {
        //return veggieNames.Count;
        return Veggies.VeggieNames.Count;
    }

    public override UITableViewCell GetCell (UITableView tableView, NSIndexPath indexPath)
    {
        var cell = tableView.DequeueReusableCell ("cell");

        if (cell == null) {
            cell = new UITableViewCell (UITableViewCellStyle.Default, "cell");

            var text = string.Format ("{0}", Veggies.VeggieNames [indexPath.Row]);
            cell.TextLabel.Text = text;

        }


        return cell;
    }

    public override void RowSelected (UITableView tableView, NSIndexPath indexPath)
    {
        Veggies.SelectedVeggie = Veggies.VeggieNames [indexPath.Row].ToString ();

    }
    #endregion


}
}

素食类

using System;
using System.Collections.Generic;

using MonoTouch.UIKit;
using MonoTouch.Foundation;

using MyDataLayer;

namespace TableViewTest
{
public static class Veggies
{
    public static List<string> VeggieNames;
    public static string SelectedVeggie;
    public static int NumberOfVeggies;

    public static int CountVeggies ()
    {
        NumberOfVeggies = DataLayer.CountRecords ("tVeggies");
        return NumberOfVeggies;
    }

    public static List<string> GetVeggieNames ()
    {
        //VeggieName ntext, Description ntext, Yummy int
        string sql = "Select VeggieName from tVeggies ORDER BY VeggieName";
        VeggieNames = DataLayer.GetStringList (sql);
        Console.WriteLine ("\n GetVeggieNames: " + VeggieNames.ToString ());
        return VeggieNames;
    }

    public static void CreateVeggie (string veggieName, int yummy, string description)
    {
        // 1. Declare variables and set initial values
        DataLayer dataLayer = new DataLayer ();
        DataField[] dataFields;

        DataField NameField = new DataField ();
        DataField YummyField = new DataField ();
        DataField DescriptionField = new DataField ();

        string sql = string.Empty;

        // unselect any other players because the new player will also become the selected player.
        MyDataLayer.DataLayer.ExecuteNonQuery (sql);

        //3. Create data field objects for each field to be created.
        NameField.FieldName = "VeggieName";
        NameField.FieldType = "string";
        NameField.FieldValue = '"' + veggieName + '"';

        YummyField.FieldName = "Yummy";
        YummyField.FieldType = "int";
        YummyField.FieldValue = yummy.ToString ();

        DescriptionField.FieldName = "Description";
        DescriptionField.FieldType = "string";
        DescriptionField.FieldValue = '"' + description + '"';

        dataFields = new DataField[] { NameField, YummyField, DescriptionField };

        // Insert Record into database.
        dataLayer.InsertRecord ("tVeggies", dataFields);

        RefreshVeggieList ();


    }

    public static void DeleteVeggie (string veggieName)
    {

        string sql = "DELETE FROM tVeggies WHERE VeggieName = '" + veggieName + "'";

        try {
            DataLayer.ExecuteNonQuery (sql);

        } catch (Exception ex) {
            Console.WriteLine ("Player.Delete error: " + ex.ToString ());
        }

        RefreshVeggieList ();

    }

    public static void UpdateVeggie (string veggieName, int yummy, string description)
    {
        // create variables and set initial values
        //DataLayer dataLayer = new DataLayer ();
        string sql = "UPDATE tVeggies SET VeggieName = '" + veggieName + "', yummy = " + yummy.ToString () + ", description = '" + description + "' where VeggieName = '" + Veggies.SelectedVeggie + "'";
        //string response = string.Empty; //this will hold a response such as "success" or the error message.

        Console.WriteLine ("Veggie.UpdateVeggie sql statement: " + sql);

        try {
            DataLayer.ExecuteNonQuery (sql);
            Console.WriteLine ("PVeggie.UpdateVeggie: veggie updated successfully.");

        } catch (Exception ex) {
            Console.WriteLine ("Veggie.UpdateVeggie: " + ex.ToString ());
        }

        RefreshVeggieList ();

    }

    // Update list of Veggie names
    // the TableView on the ManageVeggies view controller needs the VeggieList to be updated whenever veggie records are changed.
    //so the tableview will refresh properly.
    public static void RefreshVeggieList ()
    {

        string sql = "Select VeggieName from tVeggies ORDER BY VeggieName";
        VeggieNames = DataLayer.GetStringList (sql);
    }
}
}

数据层

using System;
using System.IO;
using Mono.Data.Sqlite;
using System.Data;
using System.Collections.Generic;

using MonoTouch.Foundation;
using MonoTouch.UIKit;

namespace MyDataLayer
{

// DataField class is used to create data for each data field in a table to be created, updated, or deleted.
public class DataField
{

    public string FieldName { get; set; }

    public string FieldValue { get; set; }

    public string FieldType { get; set; }
}

public class DataLayer
{   
    //declare variables used by all DataLayer methods; 
    private static string dbFileName = "myFunDatabase.db3";
    //private string dbFileAndPath = string.Empty;
    private static SqliteConnection connection;

    public DataLayer ()
    {
    }

    public static int CountRecords (string tableName)
    {
        int count = 0;
        string sql = "SELECT count(*) FROM " + tableName;
        count = DataLayer.ExecuteScalar_Int16 (sql);
        Console.WriteLine ("\n DataLayer.CountRecords: " + count.ToString () + "records found in the datatable.");


        return count;

    }
    public static void ExecuteNonQuery (string sql)
    {
        SqliteCommand sqlCommand = new SqliteCommand ();

        try {
            // create and open connection
            connection = GetConnection ();

            using (connection) {
                connection.Open ();
                Console.WriteLine ("\n DataLayer.ExecuteNonQuery: connection opened. Connection state is " + connection.State);

                // create and execute command
                sqlCommand.CommandText = sql;
                sqlCommand.Connection = connection;
                sqlCommand.ExecuteNonQuery ();
                connection.Close ();
                Console.WriteLine ("\n DataLayer.ExecuteNonQuery: Connection was closed. Connection state is " + connection.State);

            }
            connection.Close ();

            Console.WriteLine ("DataLayer.ExecuteNonQuery: NonQuery Executed: " + sql);

        } catch (Exception ex) {
            Console.WriteLine ("\n >>> DataLayer.ExecuteNonQuery Exception: " + ex.ToString ());
            Console.WriteLine ("\n >>> SQL statement: " + sql);
        }

    }

    public static Int16 ExecuteScalar_Int16 (string sql)
    {
        int result = 0;
        SqliteCommand sqlCommand = new SqliteCommand ();

        try {
            //connection = new SqliteConnection (string.Format ("Data Source = {0};", dbFileName));
            connection = GetConnection ();
            connection.Open ();

            sqlCommand.CommandText = sql;
            sqlCommand.Connection = connection;
            result = Convert.ToInt16 (sqlCommand.ExecuteScalar ());

            connection.Close ();

        } catch (Exception ex) {
            Console.WriteLine ("\n >>>DataLayer.ExecuteScalar_Int Exception: " + ex.ToString ());
        }

        return Convert.ToInt16 (result);
    }

    public static string ExecuteScalar_String (string sql)
    {
        string result = string.Empty;
        SqliteCommand sqlCommand = new SqliteCommand ();

        try {
            //connection = new SqliteConnection (string.Format ("Data Source = {0};", dbFileName));
            connection = GetConnection ();
            connection.Open ();

            sqlCommand.CommandText = sql;
            sqlCommand.Connection = connection;
            result = Convert.ToString (sqlCommand.ExecuteScalar ());

            connection.Close ();

        } catch (Exception ex) {
            Console.WriteLine ("\n >>>DataLayer.ExecuteScalar_Int Exception: " + ex.ToString ());
        }

        return result;
    }

    public void CreateDatabaseFolder ()
    {

    }


    //public string InsertRecord(string tableName, string variableNames, string variableTypes, string variableValues)
    public string InsertRecord (string tableName, DataField[] dataFields)
    {
        string sql = string.Empty;
        string fieldNameList = string.Empty;
        string fieldValueList = string.Empty;
        string response = string.Empty;
        SqliteCommand sqlCommand = new SqliteCommand ();

        connection = GetConnection ();

        try {

            connection.Open ();

            // Begin transaction for multiple updates (improves efficiency)
            sqlCommand = new SqliteCommand ("BEGIN", connection);
            sqlCommand.ExecuteNonQuery ();

            // begin individual inserts. I will nest this later to accommodate batch updates.l
            sql = "INSERT INTO " + tableName + " (";
            sqlCommand = new SqliteCommand ();
            sqlCommand.Connection = connection; 

            foreach (DataField dataField in dataFields) {
                fieldNameList += dataField.FieldName + ", ";
                fieldValueList += dataField.FieldValue + ", ";
                sqlCommand.Parameters.AddWithValue ("@" + dataField.FieldName, dataField.FieldValue);
            }

            // remove extra commas at the end of the lists, and append to the sql statement
            sql += fieldNameList.Substring (0, fieldNameList.Length - 2);
            sql += ") VALUES (";
            sql += fieldValueList.Substring (0, fieldValueList.Length - 2);
            sql += ")";

            Console.WriteLine (sql); 

            // load and run sql insert statement.
            sqlCommand.CommandText = sql;

            sqlCommand.ExecuteNonQuery ();

            sqlCommand = new SqliteCommand ("END", connection);
            sqlCommand.ExecuteNonQuery ();

            connection.Close ();

            response = "Success";
        } catch (Exception ex) {
            response = ">>> DataLayer.InsertRecord Error: " + ex.ToString ();
        }

        // End batch commmand and close connection to the database.

        Console.WriteLine ("\n DataLayer.InsertRecord Response to be returned: " + response);
        return response;
    }

    public static List<string> GetStringList (string sql)
    {
        SqliteDataReader dataReader;
        SqliteCommand sqlCommand = new SqliteCommand ();
        List<string> values = new List<string> ();

        int i = 0; //used to increment through  records.
        int count = 0; 

        connection = GetConnection ();

        try {

            using (connection) {
                connection.Open ();

                Console.WriteLine ("\n DataLayer.GetStringList: sql statement: " + sql);
                sqlCommand.CommandText = sql;


                sqlCommand.Connection = connection;

                dataReader = sqlCommand.ExecuteReader ();   
                if (dataReader.HasRows) {
                    Console.WriteLine ("\n DataLayer.GetStringList: dataReader has" + " rows. ");
                    while (dataReader.Read ()) {
                        values.Add (dataReader [0].ToString ());
                        Console.WriteLine ("\n DataLayer.GetStringList: value added to list: " + dataReader [0].ToString ());
                        i++;
                    }
                    count = i + 1;
                    Console.WriteLine ("\n DataLayer.GetStringList: dataReader has" + count + " rows. ");

                    Console.WriteLine ("\n DataLayer.GetStringList: successfully populated value string array from data reader");

                    connection.Close ();
                }
            }
        } catch (Exception ex) {
            Console.WriteLine ("\n >>> DataLayer.GetStringList  error: " + ex.ToString ());

        }

        return values;

    }

    public void GetSchema ()
    {


    }

    public static void DeleteDatabase ()
    {
        // Declare variables 
        var path = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
        string db; // full name and path of database file.

        // set initial values;
        path = Path.Combine (path, "..", "Library");
        db = Path.Combine (path, dbFileName);
        bool databaseExists = File.Exists (db);
        Console.WriteLine ("\n DataLayer.GetConnection: Getting ready to create database if it does not exist.");

        if (databaseExists) {
            try {
                File.Delete (db);
                Console.WriteLine ("\n DataLayer.DeleteDatabase: database deleted: " + dbFileName);
            } catch (Exception ex) {
                Console.WriteLine ("\n >>> DataLayer.DeleteDatabase: Unable to delete database: " + dbFileName);
                Console.WriteLine ("\n >>> DataLayer.DeleteDatabase: Cause of error: " + ex.ToString ());

            }

        }

    }

    static SqliteConnection GetConnection ()
    {
        // Declare variables 
        var path = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
        string db; // full name and path of database file.
        var conn = new SqliteConnection ();

        // set initial values;
        path = Path.Combine (path, "..", "Library");
        db = Path.Combine (path, dbFileName);
        bool databaseExists = File.Exists (db);
        Console.WriteLine ("\n DataLayer.GetConnection: Getting ready to create database if it does not exist.");

        if (!databaseExists) {

            CreateDatabase (db);
        }

        conn = new SqliteConnection ("\n Data Source=" + db);
        return conn;

    }


    static void CreateDatabase (string db)
    {
        // Declare variables 

        var conn = new SqliteConnection ();

        // set initial values;
        bool databaseExists = File.Exists (db);
        Console.WriteLine ("\n DataLayer.GetConnection: Getting ready to create database if it does not exist.");

        if (!databaseExists) {
            try {
                SqliteConnection.CreateFile (db);
                Console.WriteLine ("\n DataLayer.GetConnection: Database created successfully.");
            } catch (Exception ex) {
                Console.WriteLine ("\n >>> DataLayer.GetConnection: Error creating database: " + ex.ToString ());
            }

            if (!File.Exists (db)) {

                Console.WriteLine ("\n >>> DataLayer.GetConnection: Database NOT created.");
            }


            conn = new SqliteConnection ("Data Source=" + db);

            var commands = new[] {

                "CREATE TABLE tVeggies (VeggieName ntext, Description ntext, Yummy int)",
                "INSERT INTO tVeggies (VeggieName, Description, Yummy) VALUES ('Carrots', 'An orange root', 0)",
                "INSERT INTO tVeggies (VeggieName, Description, Yummy) VALUES ('Spinach', 'Green leafy veggie', 1)",
                "INSERT INTO tVeggies (VeggieName, Description, Yummy) VALUES ('Onion', 'Round with layers', 1)",

            };

            foreach (var cmd in commands) {


                using (var c = conn.CreateCommand()) {

                    c.CommandText = cmd;
                    //c.CommandType = CommandType.Text; //this code does not work.
                    conn.Open ();
                    c.ExecuteNonQuery ();
                    conn.Close ();
                    Console.WriteLine ("\n DataLayer.GetConnection: command executed: " + cmd.ToString ());
                }
            }
        } 
    }

    public static System.Data.DataTable GetData (string sql)
    {
        // declare variables and set initial values
        SqliteCommand command = new SqliteCommand ();
        System.Data.DataTable dataTable = new System.Data.DataTable ();
        SqliteDataAdapter adapter = new SqliteDataAdapter ();
        System.Data.DataRow iRow;

        //open connection and retrieve desired data.


        try {
            connection = GetConnection ();
            using (connection) {

                Console.WriteLine ("\n DataLayer.GetData: sql statement: " + sql);
                command.CommandText = sql;
                command.Connection = connection;
                adapter = new SqliteDataAdapter (command);

                connection.Open ();
                adapter.Fill (dataTable);

                // check to see if we got some data.
                Console.WriteLine ("\n DataLayer.GetData: retrieved dataTable with " + dataTable.Rows.Count.ToString () + " rows.");
                for (int i = 0; i< dataTable.Rows.Count; i++) {
                    iRow = dataTable.Rows [i];

                }

                Console.WriteLine ("\n DataLayer.GetData: successfully populated data table");

                connection.Close ();
            }

        } catch (Exception ex) {
            Console.WriteLine ("\n >>>   error: " + ex.ToString ());

        }

        return dataTable;

    }

}
}
4

1 回答 1

0

Looking at your code, what is visible on your screen should be directly correlated to your list of veggieNames.

So to remove, replace, or add an item:

  1. Perform this operation on the List<string>
  2. call tblVeggies.ReloadData()

You don't have to create new table source or anything, which is likely what is messing you up. I would recommend creating the table source in ViewDidLoad.

If you want to get really fancy, an optimization you can do is call tblVeggies.ReloadRows on a specific row, but I would get it working in general first.

于 2012-08-09T12:15:13.937 回答