英文:
Add row to UITableView Programmatically
问题
你正在尝试在聊天室代码中以编程方式向UITableView
添加行,但似乎无法正确实现。以下是你的代码:
public override async void ViewDidLoad()
{
// ...(略去了部分代码)...
client.OnMessageReceived += (sender2, message) =>
{
AddMessage(message);
InvokeOnMainThread(() =>
{
tblMessages.ReloadData();
});
};
// ...(略去了部分代码)...
}
public void AddMessage(string message)
{
MyMessages.Prepend(message);
source.Data = MyMessages;
InvokeOnMainThread(() =>
{
tblMessages.ReloadData();
});
}
在AddMessage
方法中,你已经将新消息添加到MyMessages
列表中,并更新了source.Data
。然后,使用InvokeOnMainThread
来确保在主线程上刷新tblMessages
,以便新消息能够正确显示在表格视图中。
这个修改应该能够让接收到的消息在UITableView
中正确显示。
英文:
I'm trying to add rows to my UITableView
programmatically in my chat room code and I can't seem to get it right. My Code:
public override async void ViewDidLoad()
{
base.ViewDidLoad();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var height = UIScreen.MainScreen.Bounds.Height;
var width = UIScreen.MainScreen.Bounds.Width;
UIImageView banner = new UIImageView();
banner.Image = UIImage.FromResource(null, "MY_TESTAPP.Resources.drawable.Banner2.jpg");
banner.Frame = new RectangleF(0, 0, (float)width, 73);
banner.ContentMode = UIViewContentMode.ScaleAspectFit;
UILabel lblTitle = new UILabel();
lblTitle.Text = theSelectedCompany + " Chat Room";
MyMessages = GetMessages();
tblMessages.LayoutIfNeeded();
source.Data = MyMessages;
tblMessages.Source = source;
UITextField txtSendingTextMessage = new UITextField(new CGRect(0, width, width, 100));
txtSendingTextMessage.Placeholder = "Enter Message To Send Here";
UIButton btnSendText = new UIButton();
CGRect ScreenBounds = UIScreen.MainScreen.Bounds;
float buttonWidth = (float)ScreenBounds.Width / 4;
btnSendText.Frame = new RectangleF(0f, 0f, buttonWidth, 50f);
btnSendText.SetTitleColor(UIColor.Black, UIControlState.Normal);
btnSendText.SetTitle("Send Text", UIControlState.Normal);
btnSendText.BackgroundColor = UIKit.UIColor.FromRGB(255, 215, 0);
View.Add(banner);
View.Add(lblTitle);
View.Add(tblMessages);
View.Add(txtSendingTextMessage);
View.Add(btnSendText);
View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
View.AddConstraints(
banner.AtTopOf(View, 50),
banner.AtRightOf(View, 0),
banner.AtLeftOf(View, 0),
lblTitle.Below(banner, 5),
lblTitle.WithSameCenterX(banner),
tblMessages.Below(lblTitle, 10),
tblMessages.AtLeftOf(View),
tblMessages.WithSameWidth(View),
tblMessages.Height().EqualTo(height/2),
txtSendingTextMessage.Below(tblMessages, 10),
txtSendingTextMessage.WithSameCenterX(tblMessages),
btnSendText.Below(txtSendingTextMessage, 10),
btnSendText.WithSameCenterX(txtSendingTextMessage)
);
client = new Client(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username, MyUser.Firstname, MyUser.Lastname, theSelectedCompany, theSelectedDept, theSelectedSection, "CHATROOM");
client.OnMessageReceived += (sender2, message) => AddMessage(message);
await client.Connect();
btnSendText.TouchUpInside += (object sender, EventArgs e) =>
{
try
{
client.SendChatMessage(theSelectedCompany, theSelectedDept, theSelectedSection, MyUser.Username, txtSendingTextMessage.Text);
txtSendingTextMessage.Text = "";
}
catch (Exception ex)
{
Utils.LogError("App:MY_TESTAPP (Messenger.cs) - An error occured in the btnSendText.TouchUpInside event, the error is: " + ex.Message + Environment.NewLine + "Trace: " + Utils.GetExceptionInfo(ex));
}
};
}
The AddMessage
code:
public void AddMessage(string message)
{
MyMessages.Prepend(message);
source = new MessageSource();
source.Data = MyMessages;
tblMessages.Source = source;
tblMessages.ReloadData();
//InvokeOnMainThread(() =>
//{
tblMessages.ReloadData();
//});
}
The UITableViewSource Code:
public class MessageSource : UITableViewSource
{
public List<string> Data { get; set; } = new List<string>();
string CellIdentifier = "TableCell";
public override nint RowsInSection(UITableView tableview, nint section)
{
return Data.Count;
}
public void Add(string Message)
{
Data.Prepend(Message);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(CellIdentifier);
string item = Data[indexPath.Row];
//if there are no cells to reuse, create a new one
if (cell == null)
{
cell = new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
}
cell.TextLabel.Text = item;
return cell;
}
}
Absolutely everything works as expected, I connect the client to the hub, I retrieve messages from the database, populate the tableview and it all displays fine. When I send a message, all other users get it, I just can't seem to add any received messages to the tableview. When messages are received the AddMessage
code is executed, it's just that the tableview never displays the changes.
答案1
得分: 0
以下是您要翻译的内容:
"又一次在我的iOS编程经历中经历了一段痛苦的篇章。
我遇到的问题是,一旦我创建了MyMessages
列表并将其分配给MessageSource
实例,我就不能再向其中添加MessageSource
将看到的任何内容了。对于像我一样的VB程序员,可以将其理解为ByRef
。我需要在MessageSource
中创建一个与Messages
视图控制器中的MyMessages
列表共享引用的列表。众所周知,ByRef
在C#类层次结构中不存在,但存在Interface
,在这种情况下是IList
,IList
是一个字符串列表的接口,现在我的代码看起来像这样:
Messages ViewController:
IList<string> MyMessages;
public override async void ViewDidLoad()
{
// 其他代码...
MyMessages = GetMessages();
// 其他代码...
}
MessageSource代码:
public class MessageSource : UITableViewSource
{
public IList<string> Data;
// 其他代码...
public void Add(string Message)
{
Data.Prepend(Message);
}
// 其他代码...
}
AddMessage代码:
public void AddMessage(string message)
{
MyMessages.Prepend(message);
InvokeOnMainThread(() =>
{
tblMessages.InsertRows(new NSIndexPath[] { NSIndexPath.FromRowSection(0, 0) }, UITableViewRowAnimation.None);
});
}
GetMessages
现在返回IList<string>
,除此之外,没有其他更改。我可以发送和接收消息并将它们添加到MyMessages
列表中,就像处理任何List
一样(MyMessages.Add(message)
)。不同之处在于,MessageSource
中的Data
现在是对内存中的字符串列表的接口,其他所有对MyMessages
的引用也是如此,因此现在每个人都在向同一个数据列表中添加内容。聊天窗口看起来很丑,我需要对其进行美化,我会的,但我首先想让功能正常运行。"
英文:
Well, another painful chapter in my iOS coding experience comes to a close.
The issue I was having is that once I created the MyMessages
list and assigned it to the MessageSource
instance, I could no longer add anything to it that MessageSource
would see. For you VB
programmers out there (like me), think ByRef
. I needed to create a list in MessageSource
that was by reference to the MyMessages
list in the Messages
view controller. Well as we all know, ByRef
doesn't exist in the c# class hierarchy but what does is Interface
, and in this case IList
, IList
is an interface to a list of strings, now my code looks like this:
Messages ViewController:
IList<string> MyMessages;
public override async void ViewDidLoad()
{
base.ViewDidLoad();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
var height = UIScreen.MainScreen.Bounds.Height;
var width = UIScreen.MainScreen.Bounds.Width;
UIImageView banner = new UIImageView();
banner.Image = UIImage.FromResource(null, "MY_TESTAPP.Resources.drawable.Banner2.jpg");
banner.Frame = new RectangleF(0, 0, (float)width, 73);
banner.ContentMode = UIViewContentMode.ScaleAspectFit;
UILabel lblTitle = new UILabel();
lblTitle.Text = theSelectedCompany + " Chat Room";
MyMessages = GetMessages();
tblMessages.LayoutIfNeeded();
source.Data = MyMessages;
tblMessages.Source = source;
UITextField txtSendingTextMessage = new UITextField(new CGRect(0, width, width, 100));
txtSendingTextMessage.Placeholder = "Enter Message To Send Here";
UIButton btnSendText = new UIButton();
CGRect ScreenBounds = UIScreen.MainScreen.Bounds;
float buttonWidth = (float)ScreenBounds.Width / 4;
btnSendText.Frame = new RectangleF(0f, 0f, buttonWidth, 50f);
btnSendText.SetTitleColor(UIColor.Black, UIControlState.Normal);
btnSendText.SetTitle("Send Text", UIControlState.Normal);
btnSendText.BackgroundColor = UIKit.UIColor.FromRGB(255, 215, 0);
View.Add(banner);
View.Add(lblTitle);
View.Add(tblMessages);
View.Add(txtSendingTextMessage);
View.Add(btnSendText);
View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
View.AddConstraints(
banner.AtTopOf(View, 50),
banner.AtRightOf(View, 0),
banner.AtLeftOf(View, 0),
lblTitle.Below(banner, 5),
lblTitle.WithSameCenterX(banner),
tblMessages.Below(lblTitle, 10),
tblMessages.AtLeftOf(View),
tblMessages.WithSameWidth(View),
tblMessages.Height().EqualTo(height/2),
txtSendingTextMessage.Below(tblMessages, 10),
txtSendingTextMessage.WithSameCenterX(tblMessages),
btnSendText.Below(txtSendingTextMessage, 10),
btnSendText.WithSameCenterX(txtSendingTextMessage)
);
tblMessages.RegisterClassForCellReuse(CellIdentifier);
client = new Client(MyUser.Firstname + " " + MyUser.Lastname, MyUser.Username, MyUser.Firstname, MyUser.Lastname, theSelectedCompany, theSelectedDept, theSelectedSection, "CHATROOM");
client.OnMessageReceived += (sender2, message) => AddMessage(message);
await client.Connect();
btnSendText.TouchUpInside += (object sender, EventArgs e) =>
{
try
{
client.SendChatMessage(theSelectedCompany, theSelectedDept, theSelectedSection, MyUser.Username, txtSendingTextMessage.Text);
txtSendingTextMessage.Text = "";
}
catch (Exception ex)
{
Utils.LogError("App:MY_TESTAPP (Messenger.cs) - An error occured in the btnSendText.TouchUpInside event, the error is: " + ex.Message + Environment.NewLine + "Trace: " + Utils.GetExceptionInfo(ex));
}
};
}
The MessageSource
code:
public class MessageSource : UITableViewSource
{
public IList<string> Data;
string CellIdentifier = "TableCell";
public override nint RowsInSection(UITableView tableview, nint section)
{
return Data.Count;
}
public void Add(string Message)
{
Data.Prepend(Message);
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
UITableViewCell cell = tableView.DequeueReusableCell(CellIdentifier);
string item = Data[indexPath.Row];
//if there are no cells to reuse, create a new one
if (cell == null)
{
cell = new UITableViewCell(UITableViewCellStyle.Default, CellIdentifier);
}
cell.TextLabel.Text = item;
return cell;
}
}
The AddMessage
code:
public void AddMessage(string message)
{
MyMessages.Prepend(message);
InvokeOnMainThread(() =>
{
tblMessages.InsertRows(new NSIndexPath[] { NSIndexPath.FromRowSection(0, 0) }, UITableViewRowAnimation.None);
});
}
GetMessages
now returns an IList<string>
other than that, nothing else changes. I can send and receive messages and add them to MyMessages
list like I would any List
(MyMessages.Add(message)
). The difference her is that Data
in MessageSource
is now an Interface
to a list of strings somewhere in memory as is every other reference to MyMessages
, so now everyone is adding to the same data list. The chat is ugly as sin and I need to pretty it up and I will, but I wanted to get the functionality to work first.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论