I'm trying to build a simple app to display the results of an API call. I can't seem to figure out how to bind my results to my data template.
The behavior i am looking for in this TestApp is that when the button is pushed the listview displays the name, party, and state of each Representative.
namespace TestApp
{
public class Reps
{
public Rep[] results { get; set; }
}
public class Rep
{
public string name { get; set; }
public string party { get; set; }
public string state { get; set; }
public string district { get; set; }
public string phone { get; set; }
public string office { get; set; }
public string link { get; set; }
public Rep() { }
public Rep(string name, string party, string state)
{
this.name = name;
this.party = party;
this.state = state;
}
}
}
namespace TestApp
{
public sealed partial class MainPage : Page
{
public ObservableCollection<Rep> Representative = new ObservableCollection<Rep>();
public MainPage()
{
this.InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
listView1.DataContext = Representative;
}
private async void Button_Click(object sender, RoutedEventArgs e)
{
var uri = new Uri("http://whoismyrepresentative.com/getall_mems.php?zip=31023&output=json");
var request = WebRequest.CreateHttp(uri);
request.Method = "GET";
request.Accept = "application/json";
var response = await request.GetResponseAsync();
var stream = response.GetResponseStream();
var deserializer = new DataContractJsonSerializer(typeof(Reps));
Reps rps = (Reps)deserializer.ReadObject(stream);
for (int i = 0; i < rps.results.Length; i++)
{
Rep newRep = new Rep { name = rps.results[i].name.ToString(),
party = rps.results[i].party.ToString(),
state = rps.results[i].state.ToString() };
Representative.Add(newRep);
Debug.WriteLine(rps.results[i].name.ToString());
}
}
}
}
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Button Content="Button"
HorizontalAlignment="Left"
Margin="275,212,0,0"
VerticalAlignment="Top"
Click="Button_Click" />
<Grid HorizontalAlignment="Left"
Height="293"
Margin="524,133,0,0"
VerticalAlignment="Top"
Width="399">
<ListView x:Name="listView1" ItemsSource="{Binding Representative}">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding name}"
FontSize="20"
Foreground="White"/>
<TextBlock Text="{Binding party}"
FontSize="20"
Foreground="White"/>
<TextBlock Text="{Binding state}"
FontSize="20"
Foreground="White"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
Setting the DataContext of the ListView only sets the context object for bindings, but it is not a binding on its own. Thus, just replace the line
listView1.DataContext = Representative;
with
listView1.ItemsSource = Representative;
Related
I have a listview in xamarin and when i try to cast the selecteditem in a button clicked event it gives me the error. The class SavedVira is for a sqlite database table, i'm trying to use async but it seems to have been more trouble then worth. (i'm very new to programing). Here is my code:
XAML:
<ListView x:Name="SavedViraView" HasUnevenRows="True" ItemTapped="SavedViraView_ItemTapped">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Padding="10">
<Label Text="Navn:" FontSize="18" FontAttributes="Bold"/>
<Label Text="{Binding Virusnavn}" FontSize="15"/>
<Label Text="Symptomer:" FontSize="18" FontAttributes="Bold"/>
<Label Text="{Binding symptom1}"/>
<Label Text="{Binding symptom2}"/>
<Label Text="{Binding symptom3}"/>
<Label Text="{Binding symptom4}"/>
<Label Text="{Binding symptom5}"/>
<Label Text="{Binding symptom6}"/>
<Label Text="Lavet af:" FontSize="18" FontAttributes="Bold"/>
<Label Text="{Binding Creator}"/>
<Button Text="Load" x:Name="LoadButton" Clicked="LoadButton_Clicked"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
XAML.CS:
private ObservableCollection<SavedVira> SavedVira = new ObservableCollection<SavedVira>();
public Åben()
{
InitializeComponent();
}
protected override void OnAppearing()
{
nameLabel.Text = Values.currentUser;
Init();
}
private async void Init()
{
BindingContext = new SavedVira();
var Viralist = await DataServices.GetSavedVira();
SavedVira = new ObservableCollection<SavedVira>(Viralist);
SavedViraView.ItemsSource = SavedVira;
}
private void LoadButton_Clicked(object sender, EventArgs e)
{
var LoadVirus = ((ListView)sender).SelectedItem as SavedVira;
if (LoadVirus == null)
return;
Values.LoadBool = true;
Values.symptomZero = LoadVirus.symptom1;
Values.symptomOne = LoadVirus.symptom2;
Values.symptomTwo = LoadVirus.symptom3;
Values.symptomThree = LoadVirus.symptom4;
Values.symptomFour = LoadVirus.symptom5;
Values.symptomFive = LoadVirus.symptom6;
}
SavedVira cast/model:
[Table("savedvira")]
public class SavedVira
{
[PrimaryKey, AutoIncrement]
[Column("id")]
public int Id { get; set; }
[Column("virusnavn")]
public string Virusnavn { get; set; }
[Column("creator")]
public string Creator { get; set; }
[Column("symptoms1")]
public string symptom1 { get; set; }
[Column("symptoms2")]
public string symptom2 { get; set; }
[Column("symptoms3")]
public string symptom3 { get; set; }
[Column("symptoms4")]
public string symptom4 { get; set; }
[Column("symptoms5")]
public string symptom5 { get; set; }
[Column("symptoms6")]
public string symptom6 { get; set; }
}
Any help would be grealty appriciated!
the sender is a Button so this doesn't work
var LoadVirus = ((ListView)sender).SelectedItem as SavedVira;
instead do this
var btn = (Button)sender;
var selected = (SavedVira)btn.BindingContext;
also, using the same name for an instance variable and a class is confusing, I'd suggest you avoid it
SavedVira = new ObservableCollection<SavedVira>(Viralist);
I created a listview where it displays all categories based on the data from an API "cat_code", and if you tapped any of the it will transfer the value of the "cat_code" into a variable "selectedItem"
MenuCategories.xaml
<ListView x:Name="MyCategory" ItemSelected="MyCategory_ItemSelected" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell >
<StackLayout Orientation="Horizontal" HorizontalOptions="Center" VerticalOptions="Center" >
<Label Font="30" HorizontalTextAlignment="Center" x:Name="categoryname" Text="{Binding cat_code}"
Style="{DynamicResource ListItemTextStyle}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
MenuCategories.xaml.cs
private string selectedItem;
public MenuCategories()
{
InitializeComponent();
GetCategoryAsync();
}
public async Task GetCategoryAsync()
{
HttpClient client = new HttpClient();
var response = await client.GetStringAsync("http://ropenrom24-001-site1.etempurl.com/potangina/final/Restserver/index.php/category/view");
var cat = JsonConvert.DeserializeObject<List<Catergory>>(response);
MyCategory.ItemsSource = cat;
}
private void MyCategory_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var selectedCategory = e.SelectedItem as Catergory;
if (selectedCategory != null)
selectedItem = selectedCategory.cat_code;
DisplayAlert("Test", "Selected: " + selectedItem, "OK");
Catergory cat = new Catergory();
{
cat.cat_code = selectedItem;
}
var json = JsonConvert.SerializeObject(cat);
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpClient client = new HttpClient();
var result = await client.PostAsync("http://ropenrom24-001-site1.etempurl.com/potangina/final/Restserver/index.php/Products/view_cat", content);
}
If I post a cat_code:Asian it will display all of cat_code that has cat_code:Asian what I want to happen is how to get the underlined in this picture?
and transfer it to a viewmodel where i can display it to this listview?
MenuView.xaml
<ListView x:Name="ViewMenu">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Image Source="{Binding menu_image ,StringFormat='https://i.imgur.com/{0:F0}.png'}" Scale="1" />
<Label Text="{Binding menu_name}" Font="30"/>
<Label Text="{Binding menu_price,StringFormat=''}"/>
<Label Text="{Binding menu_availability} "/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Menus.cs
public class Menus
{
public string menu_code { get; set; }
public string cat_code { get; set; }
public string menu_name { get; set; }
public string menu_price { get; set; }
public string menu_description { get; set; }
public string menu_image { get; set; }
public string menu_inventory { get; set; }
public string menu_availability { get; set; }
}
Basically my question is how to get the json string underlined in the picture above?
try this.
string json_response = await result.Content.ReadAsStringAsync();
the json_response should contain the data you need.
I'd like to implement a simple picker XAML binded to 3 labels, where when I choose a value from the picker the labels will be populated automatically (the data comes from SQLite).
Here is what I have:
<Picker x:Name="ListJobs" Title="Select Job" ItemsSource="{Binding options}" ItemDisplayBinding="{Binding JobNo}" SelectedItem="{Binding SelectedJobs}"/>
<Label Text="{Binding JobsId}" IsVisible="True" x:Name="TxtId"/>
<Label Text="{Binding name}" IsVisible="True" x:Name="TxtName"/>
<Label Text="{Binding location}" IsVisible="True" x:Name="TxtLoc"/>
Model
public class Jobs
{
public string JobsId {get;set;}
public string name {get;set;}
public string location {get;set;}
public Jobs(){}
}
Code Behind:
protected override OnAppearing()
{
jobsInfo = (List<Jobs>) GetJob();
foreach (var item in jobsInfo)
{
Jobs options = new Jobs
{
JobsId = item.JobsId,
name = item.name,
location = item.location
};
BindingContext = options;
}
}
private IEnumerable<Jobs> GetJobsInfo()
{
var db = _connection.Table<Jobs>();
return db.ToList();
}
I would to select from picker (like dropdown) and populate the labels.
First, there are some mistakes in your code.
1.When you go through the loop (the data you gained from db), options is always updated with new data(so it generates using last object), and you set it to BindingContext. You should set a modelView here rather a model.
2.The itemSource of Picker must be a list, however you set a model here.
3.The viewmodel must implement INotifyPropertyChanged to notify the changes.
I think what you need understanding most is not this Picker , it is How to work with binding.
Bindable Properties
Data Binding Basics
From Data Bindings to MVVM
Okay, let us come back to this case. What you need is here
I simplified the demo and you can refer to it.
XAML
<Picker x:Name="picker"
Title="Select Job"
ItemsSource="{Binding JobList}"
ItemDisplayBinding="{Binding Name}"
SelectedItem="{Binding SelectedJob}"/>
<Label Text="{Binding SelectedJob.JobsId}" IsVisible="True" x:Name="TxtId" Margin="0,100,0,0"/>
<Label Text="{Binding SelectedJob.Name}" IsVisible="True" x:Name="TxtName"/>
<Label Text="{Binding SelectedJob.Location}" IsVisible="True" x:Name="TxtLoc"/>
Model and ViewModel:
public class Jobs
{
public string JobsId { get; set; }
public string Name { get; set; }
public string Location { get; set; }
}
public class RootModel : INotifyPropertyChanged
{
List<Jobs> jobList;
public List<Jobs> JobList
{
get { return jobList; }
set
{
if (jobList != value)
{
jobList = value;
OnPropertyChanged();
}
}
}
Jobs selectedJob;
public Jobs SelectedJob
{
get { return selectedJob; }
set
{
if (selectedJob != value)
{
selectedJob = value;
OnPropertyChanged();
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Code behind:
public MainPage()
{
InitializeComponent();
this.BindingContext = new RootModel
{
JobList = GetJobsInfo()
};
}
private List<Jobs> GetJobsInfo()
{
var db = _connection.Table<Jobs>();
return db.ToList();
}
My Test:
XAML:
<Picker x:Name="ListJobs" Title="Select Job" ItemsSource="{Binding AllJobs}"
ItemDisplayBinding="{Binding Name}" SelectedItem="{Binding SelectedJob}"/>
<Label Text="{Binding SelectedJob.JobId}" IsVisible="True" x:Name="TxtId"/>
<Label Text="{Binding SelectedJob.Name}" IsVisible="True" x:Name="TxtName"/>
<Label Text="{Binding SelectedJob.Location}" IsVisible="True" x:Name="TxtLoc"/>
Model:
public class Job
{
public string JobId { get; set; }
public string Name { get; set; }
public string Location {get; set; }
}
public class JobModel
{
public List<Job> AllJobs { get; set; }
public Job SelectedJob { get; set; }
}
Code behind:
protected override OnAppearing()
{
BindingContext = new JobsModel {
AllJobs = GetJobs()
};
}
private List<Jobs> GetJobs()
{
var db = _connection.Table<Jobs>();
return db.ToList();
}
//How to add picker or dropdownlist in Xamarin forms and bind text ?
//we will be using Picker Properties -> pickername.ItemsSource and pickername.SelectedItem
//In above line pickername is the x:Name given to picker
//page.xaml
<Frame CornerRadius="5" HeightRequest="50" Padding="0">
<StackLayout Orientation="Horizontal">
<controls:BorderlessPicker
x:Name="Pickdoctype"
ItemDisplayBinding="{Binding text}"
SelectedIndexChanged="Pickdoctype_SelectedIndexChanged"
HorizontalOptions="FillAndExpand"
Title="Enter Document Type"
FontSize="20"
TextColor="Gray">
</controls:BorderlessPicker>
<ImageButton BackgroundColor="Transparent" Padding="0">
<ImageButton.Source>
<FontImageSource Glyph="" Size="25"
FontFamily="{StaticResource FontAwesomeSolid}"
Color="Gray"></FontImageSource>
</ImageButton.Source>
</ImageButton>
</StackLayout>
</Frame>
//page.xaml.cs
//Picker Get API
var responseUserData = await httpService.Get("manageDocument/documentType/documentType/" + UserID);
if (responseUserData.IsSuccessStatusCode)
{
var responseUserDataString = await responseUserData.Content.ReadAsStringAsync();
var myDeserializedClass = JsonConvert.DeserializeObject<List<DocumentTypeModel>>(responseUserDataString);
Pickdoctype.ItemsSource = myDeserializedClass;
}
//Get Picker value functionality
private void Pickdoctype_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
DocumentTypeModel selectedItem = (DocumentTypeModel)Pickdoctype.SelectedItem;
string PickerValue = selectedItem.value;
string PickerText = selectedItem.text;
}
catch (Exception ex)
{
}
}
//Create a model class
public class DocumentTypeModel
{
public string masterName { get; set; }
public string text { get; set; }
public string value { get; set; }
}
I have a ListBox which is bound to a List of DataModel.
DataModel.cs
public class DataModel
{
public string Name { get; set; }
public string Desc { get; set; }
public string Code { get; set; }
}
The ListBox should display two properties, so I have defined the ItemTemplate as below
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"></TextBlock>
<TextBlock Text=" - "></TextBlock>
<TextBlock Text="{Binding Code}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
My requirement is that the user can select which two properties to display in the ListBox at run time. I am not sure how to achieve this. I have created a sample solution to explain my problem.
MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="5">
<Label Content="Property One"></Label>
<ComboBox Name="ComboBox1" Margin="3" Width="150" ItemsSource="{Binding DataModelProperties}"></ComboBox>
<Label Content="Property Two"></Label>
<ComboBox Name="ComboBox2" Margin="3" Width="150" ItemsSource="{Binding DataModelProperties}"></ComboBox>
<Button Content="Go" Click="ButtonBase_OnClick" Margin="3"></Button>
</StackPanel>
<ListBox Grid.Row="1" ItemsSource="{Binding DataModelList}" Margin="5">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}"></TextBlock>
<TextBlock Text=" - "></TextBlock>
<TextBlock Text="{Binding Code}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
DataContext = new ViewModel();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
}
}
public class ViewModel
{
public List<String> DataModelProperties { get; set; }
public List<DataModel> DataModelList { get; set; }
public ViewModel()
{
DataModelList = new List<DataModel>();
DataModelList.Add(new DataModel() { Name = "Name1", Code = "Code1", Desc = "Desc1" });
DataModelList.Add(new DataModel() { Name = "Name2", Code = "Code2", Desc = "Desc2" });
DataModelList.Add(new DataModel() { Name = "Name3", Code = "Code3", Desc = "Desc3" });
DataModelProperties = typeof(DataModel).GetProperties().Select(s => s.Name).ToList();
}
}
public class DataModel
{
public string Name { get; set; }
public string Desc { get; set; }
public string Code { get; set; }
}
}
Things I have tried
<TextBlock Text="{Binding ElementName=ComboBox1, Path=SelectedItem}"></TextBlock>
This just displays the selected property name.
I suggest you to manage all the stuff regarding the "dynamic description" showed in the ListBox in your ViewModel.
First of all, your view model and your model should implement INotifyPropertyChanged. In my sample I created a simple base class which implements it. My base class is called NotifyPropertyChangedImpl.
Moreover I added two properties to the view model: the comboboxes for selecting the properties are binded to those two properties.
public class ViewModel : NotifyPropertyChangedImpl
{
private string property1;
private string property2;
public List<String> DataModelProperties { get; set; }
public List<DataModel> DataModelList { get; set; }
public string Property1
{
get
{
return property1;
}
set
{
if (property1 != value)
{
property1 = value;
SetDynamicDescriptions();
}
}
}
public string Property2
{
get
{
return property2;
}
set
{
if (property2 != value)
{
property2 = value;
SetDynamicDescriptions();
}
}
}
public ViewModel()
{
DataModelList = new List<DataModel>();
DataModelList.Add(new DataModel() { Name = "Name1", Code = "Code1", Desc = "Desc1" });
DataModelList.Add(new DataModel() { Name = "Name2", Code = "Code2", Desc = "Desc2" });
DataModelList.Add(new DataModel() { Name = "Name3", Code = "Code3", Desc = "Desc3" });
DataModelProperties = typeof(DataModel).GetProperties().Select(s => s.Name).ToList();
}
private void SetDynamicDescriptions()
{
PropertyInfo propertyInfo1;
PropertyInfo propertyInfo2;
Type type = typeof(DataModel);
if (!String.IsNullOrEmpty(property1) && !String.IsNullOrEmpty(property2))
{
propertyInfo1 = type.GetProperty(property1);
propertyInfo2 = type.GetProperty(property2);
foreach (DataModel dataModel in DataModelList)
{
dataModel.DynamicDescription = String.Format("{0} - {1}",
propertyInfo1.GetValue(dataModel, null), propertyInfo2.GetValue(dataModel, null));
}
}
}
}
As you can see the method SetDynamicDescriptions rebuilds the DynamicsDescription each time Property1 or Property2 changes.
I also added a property to the model class:
public class DataModel : NotifyPropertyChangedImpl
{
private string dynamicDescription;
public string Name { get; set; }
public string Desc { get; set; }
public string Code { get; set; }
public string DynamicDescription
{
get
{
return dynamicDescription;
}
set
{
if (dynamicDescription != value)
{
dynamicDescription = value;
OnPropertyChanged("DynamicDescription");
}
}
}
}
So at the end your XAML will be:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="5">
<Label Content="Property One"></Label>
<ComboBox Name="ComboBox1" Margin="3" Width="150" ItemsSource="{Binding DataModelProperties}"
SelectedItem="{Binding Property1}"></ComboBox>
<Label Content="Property Two"></Label>
<ComboBox Name="ComboBox2" Margin="3" Width="150" ItemsSource="{Binding DataModelProperties}"
SelectedItem="{Binding Property2}"></ComboBox>
</StackPanel>
<ListBox Grid.Row="1" ItemsSource="{Binding DataModelList}" Margin="5">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding DynamicDescription}" />
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
I hope this can help you.
In short, what I've done is I made 2 public properties to bind to and changed your properties to fields. Also I've made custom attribute, to control what fields user is able to select. And created a DisplayOptions class to store selection and spread it across DataModel instances.
The solution is a bit messy, considering it's a PoC, but I believe this can do:
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"></RowDefinition>
<RowDefinition Height="*"></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Margin="5">
<Label Content="Property One"></Label>
<ComboBox Name="ComboBox1" Margin="3" Width="150" ItemsSource="{Binding DataModelProperties}"></ComboBox>
<Label Content="Property Two"></Label>
<ComboBox Name="ComboBox2" Margin="3" Width="150" ItemsSource="{Binding DataModelProperties}"></ComboBox>
<Button Content="Go" Click="ButtonBase_OnClick" Margin="3"></Button>
</StackPanel>
<ListBox Grid.Row="1" ItemsSource="{Binding DataModelList}" Margin="5">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding DisplayProperty1}"></TextBlock>
<TextBlock Text=" - "></TextBlock>
<TextBlock Text="{Binding DisplayProperty2}"></TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
CS:
public partial class MainWindow : Window
{
public ViewModel model = new ViewModel();
public MainWindow()
{
InitializeComponent();
DataContext = model;
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
//This part has to be on the View side, but this is PoC
model.Opts.Prop1 = typeof(DataModel).GetFields()
.Where(a => a.Name == ComboBox1.SelectedItem.ToString()).FirstOrDefault();
model.Opts.Prop2 = typeof(DataModel).GetFields()
.Where(a => a.Name == ComboBox2.SelectedItem.ToString()).FirstOrDefault();
DataContext = null;
DataContext = model;
}
}
public class ViewModel
{
public DisplayOptions Opts = new DisplayOptions();
public List<String> DataModelProperties { get; set; }
public List<DataModel> DataModelList { get; set; }
public ViewModel()
{
var properties = typeof(DataModel).GetFields()
.Where(a => a.CustomAttributes.Any(b => b.AttributeType == typeof(SwitchableAttr)));
//Initialising options before creating DataModel instances
DataModelProperties = properties.Select(s => s.Name).ToList();
Opts.Prop1 = properties.ElementAt(0);
Opts.Prop2 = properties.ElementAt(1);
DataModelList = new List<DataModel>();
DataModelList.Add(new DataModel() { Name = "Name1", Code = "Code1", Desc = "Desc1", options = Opts });
DataModelList.Add(new DataModel() { Name = "Name2", Code = "Code2", Desc = "Desc2", options = Opts });
DataModelList.Add(new DataModel() { Name = "Name3", Code = "Code3", Desc = "Desc3", options = Opts });
}
}
public class DisplayOptions
{
public FieldInfo Prop1;
public FieldInfo Prop2;
}
public class DataModel
{
public DisplayOptions options;
[SwitchableAttr]
public string Name;
[SwitchableAttr]
public string Desc;
[SwitchableAttr]
public string Code;
public string DisplayProperty1 { get { return (string)options.Prop1.GetValue(this); } set { } }
public string DisplayProperty2 { get { return (string)options.Prop2.GetValue(this); } set { } }
}
public class SwitchableAttr : Attribute { }
This is not Complete MVVM
so here is the code
public partial class MainWindow : Window
{
private ViewModel vm;
public MainWindow()
{
InitializeComponent();
vm = new ViewModel();
this.DataContext = vm;
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
if (!string.IsNullOrEmpty(ComboBox1.Text) && !string.IsNullOrEmpty(ComboBox2.Text))
{
vm.AddDataToModel(ComboBox1.Text, ComboBox2.Text);
}
}
}
public class ViewModel
{
public List<String> DataModelProperties { get; set; }
private ObservableCollection<DataModel> _DataModelList;
public ViewModel()
{
_DataModelList = new ObservableCollection<DataModel>();
DataModelProperties = typeof(DataModel).GetProperties().Select(s => s.Name).ToList();
}
public void AddDataToModel(string cmbx1Val,string cmbx2Val)
{
_DataModelList.Add(new DataModel() { Name = cmbx1Val, Code = cmbx2Val, Desc = "Desc1" });
}
public ObservableCollection<DataModel> DataModelList
{
get
{
return _DataModelList;
}
set
{
_DataModelList = value;
}
}
}
When I click on the ListBox I notice that there are two items.
In my database there are two objects.
When I run my program the ListBox gets the two objects from the database but does not display the name of the two objects.
Here are my codes:
XAML:
<TextBox x:Name="txtSearch" Background="White" GotFocus="txtSearch_Focus" TextChanged="txtSearch_TextChanged" Text="search" FontSize="30" Height="57" Margin="19,10,19,0" Grid.Row="1" />
<!--TODO: Content should be placed within the following grid-->
<Grid Grid.Row="1" x:Name="ContentRoot" Margin="19,72,19,0">
<!--<ScrollViewer>-->
<ListBox Background="Black" x:Name="listBox" FontSize="26" Margin="0,10,0,0">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="txtEventName" TextWrapping="Wrap" Foreground="White" Width="300" Margin="10,15,0,0" Height="55"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--</ScrollViewer>-->
</Grid>
XAML.cs:
protected async override void OnNavigatedTo(NavigationEventArgs e)
{
var eventList = await App.MobileService.GetTable<Event>().ToListAsync();
foreach(Event ename in eventList)
{
eList.Add(ename.EventName);
}
this.listBox.ItemsSource = eList;
this.navigationHelper.OnNavigatedTo(e);
}
private void txtSearch_TextChanged(object sender, TextChangedEventArgs e)
{
if (eList != null)
{
var items = new List<string>();
foreach (var item in eList)
{
if (item.Contains(((TextBox)sender).Text))
items.Add(item);
}
//this.listBox.ItemsSource = items;
}
}
bool hasBeenClicked = false;
private void txtSearch_Focus(object sender, RoutedEventArgs e)
{
if (!hasBeenClicked)
{
txtSearch.Text = String.Empty;
hasBeenClicked = true;
}
}
Event class:
public class Event : IBusinessEntityBase
{
public string Id { get; set; }
public string Image { get; set; }
public string EventName { get; set; }
public string Desc { get; set; } //Description of Event
public string Category { get; set; }
public string Location { get; set; }
public DateTime Date { get; set; } //Should be data type Date
public DateTime StartingTime { get; set; } //Should be of different type (Time?)
//public DateTime EndingTime { get; set; } //Should be of different type (Time?)
//public Boolean PinnedEvent { get; set; }
//public string PinnedEvent { get; set; }
}
in the txtEventName TextBlock you must add Text={Binding EventName}.
EventName or whatever property you want to show in txtEventName.
if eList is a list of strings then your txtEventName must be like this:
<TextBlock x:Name="txtEventName" Text="{Binding}"
TextWrapping="Wrap" Foreground="White" Width="300" Margin="10,15,0,0" Height="55"/>