Dear all,
I am stucked with a data binding problem.
In my project, a simple TCP connnection checker, I create a TCPListener that handles connection of other devices.
Now what I want to do is adding the connected devices information into a ListView
The Model contains the AsynchronousSocketListener class which handles correctly the connections.
The ViewModel contains a list of TCPConnectedDevices and generates associated propertychange events.
The View (TCPPage class) creates the AsynchronousSocketListener, and a timer checks every second the list of TCPConnectedDevices updated in the Model.
When creating the Model, I insert some "test" connectedDevices into the list, this works fine, the devices are shown on the view.
Nevertheless, when a new connection occurs, the new list elements generated in the AcceptCallback are not shown.
One strange thing is that the PropertyChanged is raised in the viewmodel, and when setting breakpoints in the code (when the timer calls checkForConnectedDevices), I can see that the tcpViewModel.ConnectedDevices has 6 elements (the 5 "test" items that are shown on the view, and the new device that is not shown on the view)
Do you have an idea of what I do wrong?
Thanks in advance.
By the way, the test is done on an android device
The code follows ....
Code in the Model :
private List<TCPConnectedItem> connectedItems = new List<TCPConnectedItem>();
public AsynchronousSocketListener()
{
for (int k=0;k<5;k++)
{
// "test" connectedDevices
TCPConnectedItem tmpItem = new TCPConnectedItem();
tmpItem.IPAdress = "127.0.0." + k.ToString();
tmpItem.MACAdress = "MAC 1";// 127.0.0.1";
tmpItem.color = Color.Green;
connectedItems.Add(tmpItem);//*/
}
}
public List<TCPConnectedItem> getConnectedDevices()
{
return connectedItems;
}
public void AcceptCallback(IAsyncResult ar)
{
//Accepts connections and updates the model's list of connected devices
// Update the list:
TCPConnectedItem newItem = new TCPConnectedItem();
newItem.IPAdress = listener.LocalEndPoint.ToString();
newItem.MACAdress = listener.LocalEndPoint.ToString();
newItem.color = Color.Green;
connectedItems.Add(newItem);
}
Code in the View:
public TCPPage()
{
InitializeComponent();
tcpViewModel = new TCPViewModel();
// Set binding context:
BindingContext = tcpViewModel;
myIP = App.IP;
tcpViewModel.MyIP = App.IP; // This works fine
// Start server socket for listening to entering connections
myAsyncSocketListener = new AsynchronousSocketListener();
Thread listenerThread = new Thread(new ThreadStart(myAsyncSocketListener.StartListening));
listenerThread.Start();
//Timer
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
if (myAsyncSocketListener!=null)
{ checkForConnectedDevices(); }
return true;
});
}
private void checkForConnectedDevices()
{
List<TCPConnectedItem> updatedList= myAsyncSocketListener.getConnectedDevices();
tcpViewModel.ConnectedDevices = updatedList;
}
Code in the viewmodel:
public class TCPViewModel : INotifyPropertyChanged
{
public TCPViewModel()
{
ConnectedDevices = new List<TCPConnectedItem>();
}
public event PropertyChangedEventHandler PropertyChanged;
private List<TCPConnectedItem> connectedDevices;
public List<TCPConnectedItem> ConnectedDevices
{
get { return connectedDevices; }
set { connectedDevices = value; RaisePropertyChanged(); }
}
protected virtual void RaisePropertyChanged([CallerMemberName] string caller = "")
{
if (PropertyChanged!=null)
{
// Call the change
PropertyChanged(this, new PropertyChangedEventArgs(caller));
}
}
}
Xaml code:
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TCP.Views.TCPPage">
<ContentPage.Content>
<StackLayout Orientation="Vertical">
<ListView x:Name="lv" ItemsSource="{Binding ConnectedDevices}"><!--IsVisible="{Binding IsWiFiEnabled}">-->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<BoxView Color="{Binding color}" HeightRequest="40" WidthRequest="40"></BoxView>
<Label Text="{Binding Name}" ></Label>
<Label Text="{Binding IPAdress}" HorizontalOptions="EndAndExpand"></Label>
<Label Text="{Binding MACAdress}" HorizontalOptions="EndAndExpand"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
</ContentPage.Content>
</ContentPage>