I have a JSON like this:
I want to show the "rating" of data in gridview using the image below:
For example, the rating value is 5, it will be displayed as follows:
and if the rating is 3, it will be displayed as follows:
and if the rating is 0, it will be displayed as follows:
code:
try
{
loading.Visibility = Visibility.Visible;
string urlPath1 = "http://.../results.json?module=listing&page=1&token=3f63-dc43-c8d5-eb45-8cbf-b72d-9d98-800f";
var httpClient1 = new HttpClient(new HttpClientHandler());
var values1 = new List<KeyValuePair<string, string>>
{
};
HttpResponseMessage response1 = await httpClient1.GetAsync(urlPath1);
response1.EnsureSuccessStatusCode();
if (!response1.IsSuccessStatusCode)
{
busyIndicator.IsActive = false;
RequestException();
}
string jsonText1 = await response1.Content.ReadAsStringAsync();
JsonObject jsonObject1 = JsonObject.Parse(jsonText1);
JsonArray jsonData1 = jsonObject1["data"].GetArray();
foreach (JsonValue groupValue1 in jsonData1)
{
JsonObject groupObject2 = groupValue1.GetObject();
string title = groupObject2["title"].GetString();
double rating = groupObject2["rating"].GetNumber();
ListingClass file1 = new ListingClass();
file.Title = title;
file1.Rating = Convert.ToInt32(rating);
listingDatasource.Add(file1);
}
itemGridView.ItemsSource = listingDatasource;
busyIndicator.IsActive = false;
}
catch (HttpRequestException ex)
{
busyIndicator.IsActive = false;
RequestException();
}
How do you show the rating using the picture?
Note:
The maximum value of the rating is 5
It seems you should be able to use the third-party control, such as the UWP-Composition-Rating-Control.
W should be able to set the your images to the FilledImage and EmptyImage property of the Rating control. Then we can bind the number of the Rating in ListingClass class to the Value of the Rating control.
For example:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<GridView Name="itemGridView">
<GridView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Title}"></TextBlock>
<controls:Rating x:Name="Devils"
Value="{Binding Rating}"
Maximum="5"
ItemHeight="60"
ItemPadding="24"
StepFrequency="1"
EmptyImage="ms-appx:///Assets/empty.png"
FilledImage="ms-appx:///Assets/filled.png" />
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
Related
I have a json like the image below:
I want to put the json into a listview (inside the listview there is a webview to display the text (which I circled in blue), which is in order according to its index (which I circled in black)).
XAML:
<ListView
Name="ListPairOption"
Height="auto"
Margin="5,0,10,0">
<ListView.ItemTemplate>
<DataTemplate x:DataType="data:PairClass">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="auto"/>
</Grid.ColumnDefinitions>
<StackPanel
x:Name="pilganStack"
Grid.Column="0"
Margin="10,10,10,10">
<WebView
x:Name="option"
MaxWidth="600"
MaxHeight="300"
Margin="5,5,5,5"
local:MyProperties.HtmlString="{Binding Name}"/>
</StackPanel>
</ListView
Code:
string urlPath = "..../multiple/test/284/4";
var httpClient = new HttpClient(new HttpClientHandler());
httpClient.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", "token"));
var response = await httpClient.GetAsync(urlPath);
string jsonText = await response.Content.ReadAsStringAsync();
try
{
JsonObject jsonObject = JsonObject.Parse(jsonText);
JsonObject questionObject = jsonObject["EXAM_QUESTION"].GetObject();
int index = 0;
string c = "";
string v1 = "";
string choice = "";
ObservableCollection<PairClass> itemL = new ObservableCollection<PairClass>();
JsonArray mapArray = questionObject["map"].GetArray();
foreach (JsonValue mapValue in mapArray)
{
JsonArray mapArrayI = mapValue.GetArray();
foreach (JsonValue mapValueI in mapArrayI)
{
PairClass pair = new PairClass();
try
{
if (mapValueI.ToString().All(char.IsDigit))
{
c = String.Concat(mapValueI.ToString().Where(Char.IsDigit));
index = Int16.Parse(c);
pair.Ind = index;
}
else
{
string v = mapValueI.ToString();
var collection = Regex.Matches(v, "\\\"(.*?)\\\"");
foreach (var item in collection)
{
v1 = item.ToString().Trim('"');
choice = v1;
pair.Name = choice;
}
}
for (int i = 0; i < varian; i++)
{
itemL.Add(new PairClass { Ind = index, Name = choice });
}
itemL.Add(pair);
}
}
}
ListPairOption.ItemsSource = itemL;
}
Pair Class:
public class PairClass
{
public int Ind { get; set; }
public string Name { get; set; }
public PairClass()
{
Ind = int.MinValue;
Name = string.Empty;
Pilihan = string.Empty;
}
public PairClass(int ind, string name)
{
Ind = ind;
Name = name;
}
}
I'm having a problem, which can't display data into a ListView (only the last data is shown repeatedly in the listview), as shown below:
How to handle it?
I checked your code, it looks you generated PairClass in wrong place, it should be created before map item parsed and assigned value after each map item parsed. I have updated the code below, please check it.
try
{
JsonObject jsonObject = JsonObject.Parse(jsonText);
JsonObject questionObject = jsonObject["EXAM_QUESTION"].GetObject();
int index = 0;
string c = "";
string v1 = "";
string choice = "";
ObservableCollection<PairClass> itemL = new ObservableCollection<PairClass>();
JsonArray mapArray = questionObject["map"].GetArray();
foreach (JsonValue mapValue in mapArray)
{
JsonArray mapArrayI = mapValue.GetArray();
PairClass pair = new PairClass();
foreach (JsonValue mapValueI in mapArrayI)
{
try
{
if (mapValueI.ToString().All(char.IsDigit))
{
c = String.Concat(mapValueI.ToString().Where(Char.IsDigit));
index = Int16.Parse(c);
pair.Ind = index;
}
else
{
string v = mapValueI.ToString();
var collection = Regex.Matches(v, "\\\"(.*?)\\\"");
foreach (var item in collection)
{
v1 = item.ToString().Trim('"');
choice = v1;
pair.Name = choice;
}
}
}
catch
{
}
}
itemL.Add(pair);
}
ListPairOption.ItemsSource = itemL;
}
catch
{
}
I have a gridview with the name "majorGridView" inside a gridview with the name "assessmenGridView" whose data is data binding
XAML:
<GridView x:Name="asesmenGridView">
<GridView.ItemTemplate>
<DataTemplate>
<UserControl>
<Grid>
<StackPanel
x:Name="judulStack"
Height="40">
<TextBlock
x:Name="judulT"
Text="{Binding Title}"/>
</StackPanel>
<GridView
x:Name="majorGridView">
<GridView.ItemTemplate>
<DataTemplate>
<UserControl>
<Grid>
<TextBlock
x:Name="kelasT"
Text="{Binding Major}"/>
</Grid>
</UserControl>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
</Grid>
</UserControl>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
How to display binding text on "majorGridView" ? Because if I use the code below, I will get an error message: "The name 'majorGridView' does not exist in the current context"
Code:
ObservableCollection<Ujian> ujiandatasource = new ObservableCollection<Ujian>();
ObservableCollection<Ujian> majordatasource = new ObservableCollection<Ujian>();
string urlPath = "https://pto.study.id/api/" + ((App)(App.Current)).AsesmenCode + "-do/s2/choose-exam/" + guru.ID;
var httpClient = new HttpClient(new HttpClientHandler());
httpClient.DefaultRequestHeaders.Add("Authorization",
string.Format("Bearer {0}", tkn));
var response = await httpClient.GetAsync(urlPath);
string jsonText = await response.Content.ReadAsStringAsync();
try
{
JsonArray jsonArray = JsonArray.Parse(jsonText);
foreach (JsonValue groupValue in jsonArray)
{
JsonObject groupObject = groupValue.GetObject();
JsonArray majorArray = groupObject["majors"].GetArray();
foreach(JsonValue majorValue in majorArray)
{
JsonObject majorObject = majorValue.GetObject();
string major = majorObject["major"].GetString();
Ujian ujian1 = new Ujian();
ujian1.Major = major + ", ";
majordatasource.Add(ujian1);
majorGridView.ItemsSource = majordatasource;
}
Ujian ujian = new Ujian();
ujian.Title = title;
ujiandatasource.Add(ujian);
asesmenGridView.ItemsSource = ujiandatasource;
}
Ujian.cs
class Ujian
{
public string Title { get; set; }
public string Major { get; set; }
}
}
The name 'majorGridView' does not exist in the current context"
majorGridView in the parent DataTemplate, so we can't access majorGridView with name directly. For this scenario, we often use nested collection apply the value generally. And here is similar case that you could refer to.
I'm getting data from api via async task:
public async Task<PostModel.Post[]> GetPostsAsync()
{
var client = new HttpClient();
var uri = new Uri("link here");
var response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
var jsonString = await response.Content.ReadAsStringAsync();
var rootObject = JsonConvert.DeserializeObject<PostModel.Post[]>(jsonString);
return rootObject;
}
else
return null;
}
Also I've created a simple vertical view:
<ContentPage.Content>
<ListView x:Name="MainView">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical" HorizontalOptions="Fill" VerticalOptions="Fill" BackgroundColor="WhiteSmoke">
<Frame OutlineColor="Black">
<Label x:Name="Title" Text="{Binding Name}"/>
<Image x:Name="Image" Source="{Binding path}" />
</Frame>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</ContentPage.Content>
Wrote a custom cell for displaying data:
public CustomCell()
{
//instantiate items in views
var Image = new Image();
var NameLabel = new Label();
var horizontalLayout = new StackLayout() { BackgroundColor = Color.WhiteSmoke };
//set bindings
NameLabel.SetBinding(Label.TextProperty, new Binding("Name"));
Image.SetBinding(Image.SourceProperty, new Binding("path"));
Image.HorizontalOptions = LayoutOptions.Center;
Image.HeightRequest = 600;
Image.WidthRequest = 600;
NameLabel.FontSize = 24;
//add views to the view hierarchy
horizontalLayout.Children.Add(NameLabel);
horizontalLayout.Children.Add(Image);
//add to parent view
View = horizontalLayout;
}
Now I'd like to populate layout from the async task dynamically. For example if task gets 6 items - create 6 cells with data from each of the async task items. Any suggestions how can i do it? I'm completely green in xamarin.forms and just started trying it.
in OnAppearing, just set the source for your ListView
MainView.ItemSource = await GetPostsAsync();
I have an image binding on gridview with XAML below:
<Border x:Name="coverBox" Grid.Row="0" Margin="5,10,0,0" Width="230" Height="170" VerticalAlignment="Top" HorizontalAlignment="Left" BorderBrush="Gray" BorderThickness="1" Background="{x:Null}">
<Image x:Name="cover" Source="{Binding Thumbnail}" HorizontalAlignment="Center" Stretch="Uniform" AutomationProperties.Name="{Binding Title}" Width="230" Height="170"/>
</Border>
Code:
string urlPath1 = "http://..../API/sekolah";
var httpClient1 = new HttpClient(new HttpClientHandler());
var values1 = new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("api_key", "...."),
new KeyValuePair<string, string>("limit", limit++.ToString()),
new KeyValuePair<string, string>("hal", noHal++.ToString())
};
var response1 = await httpClient1.PostAsync(urlPath1, new FormUrlEncodedContent(values1));
response1.EnsureSuccessStatusCode();
if (!response1.IsSuccessStatusCode)
{
busyIndicator.IsActive = false;
RequestException();
}
string jsonText1 = await response1.Content.ReadAsStringAsync();
JsonObject jsonObject1 = JsonObject.Parse(jsonText1);
JsonArray jsonData1 = jsonObject1["data"].GetArray();
foreach (JsonValue groupValue1 in jsonData1)
{
JsonObject groupObject2 = groupValue1.GetObject();
string thumbnail = groupObject2.ContainsKey("thumbnail") && groupObject2["thumbnail"] != null ? groupObject2["thumbnail"].GetString() : string.Empty;
ListingClass file1 = new ListingClass();
file1.Thumbnail = thumbnail;
listingDatasourceDetail.Add(file1);
}
listingGridView.ItemsSource = listingDatasourceDetail;
I want while still loading to take the image data from JSON, then show the paceholder images/SEKOLAH-place-holder-600.png first
How to add placeholder while still loading?
Wrap your cover Image within a Grid, then create another Image to display the placeholder png and place it behind cover.
Try add Loading event to Image :
private void myimage_Loading(FrameworkElement sender, object args)
{
Image myimage = (Image)sender;
myimage.Source = new BitmapImage(new Uri("ms-appx:///images/SEKOLAH-place-holder-600.png"));
}
I'm having a problem with a ListView for Windows Phone:
I'm using a databinding to display all items in a folder, but when I try to iterate through them, I don't get a control, but the class I use to get the items in the LocalFolder of the app (The subjectpicker class)!
SubjectPicker class:
class SubjectPicker {
public static async Task<List<SubjectPicker>> SubjectData() {
List<string> Names = new List<string>();
List<Brush> Colors = new List<Brush>();
List<string> Items = new List<string>();
List<List<TestOrTask>> TestsAndTasks = new List<List<TestOrTask>>();
StorageFolder LocalFolder = ApplicationData.Current.LocalFolder;
var files = await LocalFolder.GetFilesAsync();
foreach (var file in files) {
//await file.DeleteAsync();
List<TestOrTask> TAT = new List<TestOrTask>();
Names.Add(file.DisplayName);
bool readItems = false;
var contents = await FileIO.ReadLinesAsync(file);
foreach (var content in contents) {
if (content.Contains("Subject Color")) {
string colorname = content.Replace("Subject Color: ", "");
Colors.Add(ColorConverter.fromString_Brush(colorname));
}
else if (content == "<Items>") readItems = true;
else if (content == "</Items>") readItems = false;
if (readItems == true && content != "") {
// Layout: <Name>: <Score>/<Maximum>|<YYYY>/<MM>/<DD>
string name = content.Split(':')[0];
string Score = content.Split(':')[1].Replace(" ", "");
string Date = content.Split('|')[1];
TestOrTask TOT = new TestOrTask(
name,
double.Parse(Score.Split('/')[0]),
double.Parse(Score.Split('/')[1]),
new DateTime(
Int32.Parse(Date.Split('/')[0]),
Int32.Parse(Date.Split('/')[1]),
Int32.Parse(Date.Split('/')[2])));
TAT.Add(TOT);
}
}
Items.Add("Aantal Testen & Taken: " + TAT.Count.ToString());
TestsAndTasks.Add(TAT);
}
var data = new List<SubjectPicker>();
for (int i = 0; i < Names.Count; i++) {
data.Add(new SubjectPicker(Names[i], Colors[i], Items[i], TestsAndTasks[i]));
}
return data;
}
public SubjectPicker(string name, Brush color, string itemstotal, List<TestOrTask> TestsAndTasks) {
PickerName = name;
PickerColor = color;
ItemTotal = itemstotal;
this.TestsAndTasks = TestsAndTasks;
}
public string PickerName { get; set; }
public Brush PickerColor { get; set; }
public string ItemTotal { get; set; }
public List<TestOrTask> TestsAndTasks = new List<TestOrTask>();
}
Xaml Code:
<Page.Resources>
<DataTemplate x:Key="SubjectTemplate">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Border Margin="0,9.5,0,0" Background="Transparent" >
<Rectangle Height="50" Width="50" Fill="{Binding PickerColor}" RadiusX="5" RadiusY="5"/>
</Border>
<StackPanel Grid.Column="1" Margin="14.5,0,0,0">
<TextBlock Text="{Binding PickerName}" Style="{ThemeResource ListViewItemTextBlockStyle}" />
<TextBlock Text="{Binding ItemTotal}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}" />
</StackPanel>
</Grid>
</DataTemplate>
</Page.Resources>
<Page.BottomAppBar>
<CommandBar x:Name="AppBar" Visibility="Collapsed">
<AppBarButton x:Name="EditSubject" Icon="Edit" Label="Aanpassen" Click="EditSubject_Click"/>
<AppBarButton x:Name="DeleteSubject" Icon="Delete" Label="Verwijderen" Click="DeleteSubject_Click"/>
</CommandBar>
</Page.BottomAppBar>
<Grid x:Name="MainGrid" Loaded="MainGrid_Loaded">
<Controls:TopBarControl x:Name="TopBarControl" Margin="0" VerticalAlignment="Top" PageName="Vakken" ControlsVisible="All" Width="Auto" BackButtonClicked="TopBar_BackButtonClicked" AddButtonClicked="TopBar_AddButtonClicked" EditButtonClicked="TopBar_EditButtonClicked"/>
<Grid x:Name="ControlsGrid" Margin="0,50,0,-60" Tapped="ControlsGrid_Tapped">
<ListView x:Name="SubjectList" ItemsSource="{Binding}" ItemTemplate="{StaticResource SubjectTemplate}"/>
</Grid>
</Grid>
Void to iterate through:
private async Task SelectSubjects() {
for (int i = 0; i < SubjectList.Items.Count; i++) {
var control = SubjectList.Items[i];
Grid subject = control as Grid;
if (subject != null) {
subject.Background = new SolidColorBrush(SchoolToolsColors.AppColor);
await Task.Delay(TimeSpan.FromMilliseconds(50));
}
}
isSelecting = true;
AppBarVisible = Visibility.Visible;
}
Thanks in advance!!!
When iterating on databinded control you'll always get its underlying data.
You should Style.Triggers to alter UI based on data (changing background, showing/hiding controls, etc.).
However, there is a way to go with altering UI from C# but that would make XAML and code-behind tightly coupled => that introduces more complexity into your code - simply believe me, it is not what you want/need.