I'm trying to insert certain pieces of data of a user into a ListView, but can't seem to get any of them to show up.
This is how my code looks like so far. The issue is in the last two classes (Invite_Page.xaml.cs and Invite_Page.xaml), but I also pasted my notes from other classes which could be relevant.:
User.cs:
public class User {
public string fName { get; set; }
public string lName { get; set; }
public string uName { get; set; }
public string Pw { get; set; }
// public string cls { get; set; }
}
fName and lName are both Strings
DatabaseManager.cs:
public class DatabaseManager
{
SQLiteConnection dbConnection;
public DatabaseManager()
{
dbConnection = DependencyService.Get<IDBInterface>().CreateConnection();
}
public List<User> GetAllUsers()
return dbConnection.Query<User>("Select * From [User]");
public int SaveUser(User aUser)
{
//dbConnection.CreateTable<User>();
//return 1;
return dbConnection.Insert(aUser);
}
public List<User> GetAllNames()
return dbConnection.Query<User>("Select fName, lName From [User] ORDER BY fName;");
//.....
Invite_Page.xaml:
<ListView
x:Name="invitees"
SeparatorColor="White"
BackgroundColor="Transparent"
ItemsSource="{Binding invitees}"
IsGroupingEnabled="true"
IsPullToRefreshEnabled="true"
ItemTapped="Handle_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding}" TextColor="White"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Invite_Page.xaml.cs:
DatabaseManager DBM = new DatabaseManager();
// List<User> Invitees(String SearchText = null)
// {
// invitees.ItemsSource = DBM.GetAllNames();
// return Invitees();
// }
protected override void OnAppearing()
{
base.OnAppearing();
invitees.ItemsSource = DBM.GetAllNames();
}
In the Invite_Page.xaml.cs code, you can see that I tried inputting the data by using the code that is commented out. The result of that was that nothing showed up in the list. But with the second method which isn't commented out, the result was that "RoseySports.User" was placed in the ListView. I'm trying to make it so that the values of fName and lName are put together as one string, and are placed in the ListView.
The easiest way is to override ToString() method of the User class:
public override string ToString()
{
return fName + " " + lName;
}
The other option is to build more complicated DataTemplate as #ViralThakker mentioned.
P.S. The line ItemsSource="{Binding invitees}" in your XAML is unusable if you are assigning ItemsSource in code.
First, you have to specify what you really want from the model of User to the TextCell that you use binding. You set as ItemSource Users, but you just set TextCell Binding without any variable. Try to set Text={Binding fName} for example.
Second, try to use ViewModel to populate data. Learn more here: https://learn.microsoft.com/en-us/xamarin/xamarin-forms/enterprise-application-patterns/mvvm
You need to create Custom List item template to display value from your object.
For example you want to display fName,lName and uName then you'll have to use below code for binding values to list item
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" Padding="10">
<Label Text="{Binding fName}" TextColor="White"/>
<Label Text="{Binding lName}" TextColor="White"/>
<Label Text="{Binding uName}" TextColor="White"/>
</StackLayout>
</ViewCell>
</DataTemplate>
Related
Cannot figure out a proper way get an item from ListView.
My XAML bindings:
<ListView x:Name="MyListView" ItemTapped="MyListView_ItemTapped" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding Name}"></Label>
<Label Text="{Binding Email}"></Label>
<Image Source="{Binding PhotoUrl}" WidthRequest="20" HeightRequest="20"></Image>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
All the data gets displayed and works fine. Class is called Forums:
[JsonProperty("results")]
public List<Result> Results { get; set; }
public class Result
{
[JsonProperty("name")]
public string Name { get; set; }
[JsonProperty("email")]
public string Email { get; set; }
[JsonProperty("photoUrl")]
public string PhotoUrl { get; set; }
}
I have made MyListView_ItemTapped Function and for now, I'm trying to display its name when the item is tapped on, but not sure what is a proper way to do it. And I always think that I'm just bodging some random things together until I get something.
private void MyListView_ItemTapped(object sender, ItemTappedEventArgs e)
{
var index = forums.Results.IndexOf(e.Item as Forums.Result);
DisplayAlert("Alert", forums.Results[index].Name, "OK");
}
So if anyone could point me to the better direction or even give few better examples or just explain how should it be done.
just cast e.Item to the correct type
var item = e.Item as Forums.Result;
// then use item.Name, etc...
You can also use selected item property
<ListView **SelectedItem="{Binding Result, Mode=TwoWay}">**
code behind:
`private Result _result;
public Result Result
{
get { return _deviceSession; }
set
{
SetProperty(ref _deviceSession, value);
}
}`
From this class object you can able to get all data
You can cast to the correct Class
private void MyListView_ItemTapped(object sender, ItemTappedEventArgs e)
{
var index = forums.Results.IndexOf(e.Item as Forums.Result);
var selectedItem = (Forums.Result)e.Item;
if(selectedItem != null)
{
DisplayAlert("Alert", selected|Item.Name, "OK");
}
}
Oh and if you want to remove the selecteditem effect just
if (sender is ListView lv) lv.SelectedItem = null;
I just dived in to Xamarin Forms and using Azure.
I am able to successfully call the row from the database but it's displaying something into the ListView instead of what I want it to display.
My codes:
private async void generateList()
{
var clientUsers = await App.MobileService.GetTable<iSoftTicket.Model.TblUser>().Where(u => u.uc_category == "Client").ToListAsync();
lvClient.ItemsSource = clientUsers;
}
I want it to display the column with Gulfden on it. Any help is appreciated.
Thanks.
You should create your ListView's ItemTemplate(e.g. ViewCell) and then add some label to display your data like:
<ListView x:Name="MyListView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Admin}"/>
<Label Text="{Binding Tickets}"/>
<Label Text="{Binding Clients}"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I notice that you have set your listview's ItemSource, please make sure your model's property names is Corresponding to the Binding name in the XAML, you can refer to my sample in code behind:
ObservableCollection<MyModel> list = new ObservableCollection<MyModel>();
for (int i=0; i<10; i++)
{
list.Add(new MyModel { Admin = "admin" + i, Clients = "client", Tickets = "tickets" });
}
MyListView.ItemsSource = list;
public class MyModel
{
public string Admin { set; get; }
public string Tickets { get; set; }
public string Clients { get; set; }
}
I am building a WPF app that will populate filtered headlines from a variety of news services. Each headline triggers an event, which in a console app I can display on the console. I want to use WPF here but have bot used it prior to this endeavor. My mainwindow xaml is as shown below. My original thought was to have an ObservableCollection populate list items in a listview in the xaml. If that is not the right approach, I'm open to expert opinion on a better way as speed of receipt to display is vital. If what I am doing is proper then how do I bind a new entry to the ObservableCollection to a new list item to display?
<StackPanel Orientation="Vertical" Margin="5,150 5 50" Name="HeadlinePanel">
<TextBlock Text="Filtered Headlines From Monitoring List"
HorizontalAlignment="Left" Margin="0,0 5 5" Name="ScrollingHeadlineLabel" FontWeight="Bold" FontSize="14" Background="LightSkyBlue" />
<ListBox>
<ListBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="a property on the headline" />
<TextBlock><Run Text="headline is from a website"/></TextBlock>
</StackPanel>
</ListBoxItem>
<ListBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="a property on the headline" />
<TextBlock><Run Text="headline is from TWTR"/></TextBlock>
</StackPanel>
</ListBoxItem>
<ListBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="a property on the headline" />
<TextBlock><Run Text="headline from a different website"/></TextBlock>
</StackPanel>
</ListBoxItem>
<ListBoxItem>
<StackPanel Orientation="Horizontal">
<Image Source="a property on the headline" />
<TextBlock><Run Text="text from a different tweet"/></TextBlock>
</StackPanel>
</ListBoxItem>
</ListBox>
</StackPanel>
In the console app the streaming begins (code shown below) in the filteredStream.Start() but the handler needs to register prior. In the console app I can write to the console (commented out) but here I add the headline object to the collection when the event fires. My question is how to bind that to my xaml list items. I will initiate the stream from mainwindow method? or some method I create to run within that?
var config = new TwitterOAuthConfig()
{
ConsumerKey = customerKey,
ConsumerSecret = customerSecret,
AccessToken = accessToken,
AccessTokenSecret = accessTokenSecret,
GeoOnly = false,
KeywordsToMonitor = keywords,
UsersToFollow = followers
};
var filteredStream = new TwitterClient(config);
var headlineCollection = new ObservableCollection<Headline>();
// subscribe to the event handler
filteredStream.HeadlineReceivedEvent +=
(sender, arguments) => headlineCollection.Add(arguments.Headline);
//Console.WriteLine("ID: {0} said {1}", arguments.Headline.Username, arguments.Headline.HeadlineText);
filteredStream.ExceptionReceived += (sender, exception) => Console.WriteLine(exception.HeadlineException.ResponseMessage);
filteredStream.Start();
Here is my Original HeadlineViewModel
public class HeadlineViewModel : ObservableItem
{
private string _headlineText;
public string Source { get; set; }
public string Username { get; set; }
public string Text
{
get { return _headlineText; }
set
{
_headlineText = value;
RaisePropertyChangedEvent("HeadlineText");
}
}
public List<string> UrlsParsedFromText { get; set; }
public string TimeStamp { get; set; }
}
I've updated it to the following:
public class HeadlineViewModel
{
public class HeadlineDisplayItems: ObservableItem
{
private string _headlineText;
public string HeadlineIconPath { get; set; }
public string TimeStamp { get; set; }
public string Username { get; set; }
public string Text
{
get { return _headlineText; }
set
{
_headlineText = value;
RaisePropertyChangedEvent("HeadlineText");
}
}
}
public List<string> UrlsParsedFromText { get; set; }
public ObservableCollection<HeadlineDisplayItems> HeadlineCollection { get; set; }
}
I don't know about your architecture, but wpf is mostly used with what they call MVVM (Model-View-ViewModel) where you have your View (you already posted the code), the ViewModel (I believe you don't have one) and the model (that is the Headline you are using). The objective of the ViewModel is to simplify the life of the view and make available all the information and actions it needs to display.
For example, you should hava a ViewModel for the whole view you are building, let's say "HeadlinePanelViewModel" (I don't recommend panel in the name because the idea of using a ViewModel is to abstract the controls or technologies being used). The HeadlinePanelViewModel needs to make the headlines available, so it must have a collection of a ViewModel representing all the information concerned to the headline (icons, titles, links, ...). In the end, you have an HeadlinePanelViewModel which contains an ObservableCollection. Set this as DataContext of your View and you must be ready to go to display your info.
Now comes the part of actually loading the info. Again, I don't know about your architecture. But in VERY simple terms, you could instantiate the filteredStream inside of your HeadlinePanelViewModel and everytime an HeadlineReceivedEvent is fired, you create an HeadlineViewModel corresponding to it and add to your collection.
"Complete" code based in the code in your answer:
The ViewModel:
public class HeadlineViewModel
{
public HeadlineViewModel()
{
// This is here only for simplicity. Put elsewhere
var config = new TwitterOAuthConfig()
{
ConsumerKey = customerKey,
ConsumerSecret = customerSecret,
AccessToken = accessToken,
AccessTokenSecret = accessTokenSecret,
GeoOnly = false,
KeywordsToMonitor = keywords,
UsersToFollow = followers
};
var filteredStream = new TwitterClient(config);
HeadlineCollection = new ObservableCollection<HeadlineDisplayItems>();
// subscribe to the event handler
filteredStream.HeadlineReceivedEvent +=
(sender, arguments) => HeadlineCollection.Add(ConvertToViewModel(arguments.Headline));
//Console.WriteLine("ID: {0} said {1}", arguments.Headline.Username, arguments.Headline.HeadlineText);
filteredStream.ExceptionReceived += (sender, exception) => Console.WriteLine(exception.HeadlineException.ResponseMessage);
filteredStream.Start();
}
private HeadlineDisplayItems ConvertToViewModel(Headline headline)
{
// Conversion code here
}
public class HeadlineDisplayItems: ObservableItem
{
private string _headlineText;
public string HeadlineIconPath { get; set; }
public string TimeStamp { get; set; }
public string Username { get; set; }
public string Text
{
get { return _headlineText; }
set
{
_headlineText = value;
RaisePropertyChangedEvent("HeadlineText");
}
}
}
public List<string> UrlsParsedFromText { get; set; }
public ObservableCollection<HeadlineDisplayItems> HeadlineCollection { get; set; }
}
The View:
<StackPanel Orientation="Vertical" Margin="5,150 5 50" Name="HeadlinePanel">
<TextBlock Text="Filtered Headlines From Monitoring List"
HorizontalAlignment="Left" Margin="0,0 5 5" Name="ScrollingHeadlineLabel" FontWeight="Bold" FontSize="14" Background="LightSkyBlue" />
<ListBox ItemsSource="{Binding HeadlineCollection}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Source="{Binding HeadlineIconPath}" />
<TextBlock><Run Text="{Binding Text}"/></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
The code missing is where you do the this.DataContext = new HeadlineViewModel(); to the View.
EDIT: You may experience some problems with cross-thread operations if you try to update the observableCollection from a thread different of the view thread. A workaround is to use the solution in this link, but I don't think it's the best approach.
Create your ObservableCollection as a Property that you can Reference in XAML. Either create it directly in your MainWindow-Class or instantiate your collection as a StaticResource.
Bind your ObservableCollection as ItemsSource to your Listbox
<ListBox ItemsSource="{Binding Path=HeadlineCollection}"></ListBox>
and use an DataTemplate to bind your data to it
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image ... />
<TextBlock Text="{Binding Path=Text}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
For the Headline, create a data class that manages what you need to display (headline, icons, etc.). Something like this:
class Headline
{
bool isTwitter {get; set;}
string Text {get; set;}
}
Then in your client object you can simply add a new object to the ObservableCollection by calling the Add()-Method and the Application will automatically render the new object.
You can start your query client on the main UI thread but for a responsive UI you should let the query routine run in it's own thread (e.g. by using a BackgroundWorker) so that the UI isn't cluttered by it.
I have searched the web for the last few days but can't seem to find something that I would have thought was quite a simple task. I would like to add a resource in my XAML page of my windows phone application which will reference a complex object but I can't find the correct method. Is this possible? Object is made up something similar to:
Public class ComplexClass
{
Public string name { get; set; }
Public int ID { get; set; }
Public observablecollection<SimpleClass> simpleObjects { get; set; }
Public addSimpleObject(SimpleClass newSimpleObject)
{
if (simpleObjects == null)
simpleObjects = new ObservableCollection<SimpleClass>();
simpleObjects.Add(newSimpleObject);
}
}
Public Class SimpleClass
{
Public String Name { get; set; }
Public String Disc { get; set; }
}
You could use MVVM do achieve this. There are already heaps of tutorials available that you can access to show you how to follow this design pattern, so I won't go into that.
Instead I'll just show you a simple way of getting the data to your view.
In the constructor of your UserControl (or Page or whatever), set up the DataContext to an instance of your ComplexClass:
ComplexClass complexClass;
public MyUserControl1()
{
complexClass = new ComplexClass();
complexClass.AddSimpleObject(new SimpleClass { Name = "Bob" });
this.DataContext = complexClass;
this.InitializeComponent();
}
Then in your XAML you can bind to it like this:
<StackPanel>
<!-- Binding to properties on ComplexClass -->
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding ID}" />
<ListView ItemsSource="{Binding SimpleObjects}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<!-- Binding to properties on SimpleClass -->
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Disc}" />
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
Without knowing specifics of your code, it's hard for me to suggest a method that is most suitable for you. I'd read up on MVVM and view models.
I was trying to get it working for few days.
What is wrong in this code?
This is my window XAML:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Rapideo_Client"
x:Class="Rapideo_Client.MainWindow"
Title="NVM" SnapsToDevicePixels="True" Height="400" Width="625">
<Window.Resources>
<DataTemplate x:Key="linksTemplate" DataType="DownloadLink">
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Path=Name}" FontWeight="Bold"></TextBlock>
<Label Content="{Binding Path=SizeInMB}"/>
<Label Content="{Binding Path=Url}"/>
</StackPanel>
</DataTemplate>
</Window.Resources>
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
x:Name="MainListBox"
ItemTemplate="{DynamicResource linksTemplate}">
</ListView>
</Window>
This is my class:
class Rapideo
{
(...)
public List<DownloadLink> Links { get; private set; }
(...)
}
This is my item:
class DownloadLink
{
public string Name { get; private set; }
public string Url { get; private set; }
public DateTime ExpiryDate { get; private set; }
public float SizeInMB { get; private set; }
public int Path { get; private set; }
public string Value { get; private set; }
public LinkState State { get; set; }
public enum LinkState
{
Ready, Downloading, Prepering, Downloaded
}
public DownloadLink(string name, string url, DateTime expiryDate, float sizeInMB, int path, string value, LinkState state)
{
Name = name;
Url = url;
ExpiryDate = expiryDate;
SizeInMB = sizeInMB;
Path = path;
Value = value;
State = state;
}
}
This is my binding:
RapideoAccount = new Rapideo();
MainListBox.ItemsSource = RapideoAccount.Links;
Later in the code I populate that list in RapideoAccount.Links.
But nothing is showing in ListView.
List View is always empty.
Where is mistake in that code?
Yes, it should be an ObservableCollection<DownloadLink> if you're planning on adding to it AFTER you have setup the ItemsSource. If the list is preloaded and you won't be changing it, List<T> would have worked.
Now I do think that
MainListBox.ItemsSource = RapideoAccount.Links;
is still technically a binding. But what you are probably thinking of is binding via the DataContext rather than directly (al la MVVM style). So that'd be:
RapideoAccount = new Rapideo();
this.DataContext = RapideoAccount;
Then in your window, you'd bind your ItemSource like this:
<Window
...
<ListView ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Visible"
x:Name="MainListBox"
ItemsSource="{Binding Links}"
ItemTemplate="{DynamicResource linksTemplate}">
</ListView>
</Window>
First off, you should use an ObservableCollection<DownloadLink> rather than a List<DownloadLink> if you're planning on making changes to the list after setting up the binding.
Second of all, just to be clear:
MainListBox.ItemsSource = RapideoAccount.Links;
is not a binding. You're just setting the property. That will work for certain scenarios, but its not really a binding like we normally talk about in WPF.
I think that Links needs to be an ObservableCollection, not a List.