0

テーブルビューを更新する方法についてアドバイスをくれた Jonathan Peppers に感謝します。


更新: ここに私のソリューションへのリンクがあります: https://github.com/Videlia/Veggies.git。また、横向きビューで 5 つのアイテムを追加したり、縦向きビューで約 7 つまたは 8 つのアイテムを追加したりすると、リストを下に表示するのではなく、一番上のアイテムが再度表示されるようになることを発見しました。ただし、行を選択すると、表示されるべき値が選択されます。

行を追加または編集すると、テーブルビューが完全に機能するようになりました (どちらの場合も、別の画面に移動してからこの画面に戻る必要があります)。同じ画面で削除操作を実行すると、何らかの理由でデータがリロードされません。

これが私の更新されたコードです:

ビューコントローラー

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

コードを見ると、画面に表示されているものは のリストに直接関連付けられているはずですveggieNames

アイテムを削除、置換、または追加するには:

  1. でこの操作を実行します。List<string>
  2. 電話tblVeggies.ReloadData()

新しいテーブル ソースなどを作成する必要はありません。でテーブル ソースを作成することをお勧めしますViewDidLoad

あなたが本当に派手になりたいなら、あなたができる最適化はtblVeggies.ReloadRows特定の行で呼び出すことですが、私は最初にそれを一般的に機能させるでしょう。

于 2012-08-09T12:15:13.937 に答える