In my View Model
public ObservableCollection<AddExpenses> _expenses;
public ObservableCollection<AddExpenses> Expenses
{
get
{
if (_expenses == null)
{
_expenses = new ObserrvableCollection<AddExpenses>();
}
return _expenses;
}
}
public ICommand click { get; set; }
public TransactionViewModel(Register_person logindata)
{
click = new Command(add)
}
private void add()
{
var database = new Database();
var expenses = database.GetFinalExpense(10);
foreach (var expense in expenses)
{
Expenses.Add(expense);
}
}
In my database.cs
public AddExpenses[] GetFinalExpense(int numberOfExpenses)
{
return Conn.Table<AddExpenses>()
.OrderByDescending(expenses => expenses.Id)
.Take(numberOfExpenses)
.ToArray();
}
I used this code to add these last ten record to my list view using this code.
when I called the GetFinalExpense(10) it takes all last 10 records.but when I execute the add function it only shows the two data one is type is DateTime and other is Double. my other two data are in string format. Data binding and XAML part has no issue as far as I know(not Entirely sure)
here my XAML
<ListView ItemsSource="{Binding Expenses}" VerticalOptions="FillAndExpand" >
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<Label Text="{Binding Catagoryview}"/>
<Label Text="{Binding Date}"/>
<Label Text="{Binding Expense}"/>
<Label Text="{Binding username}"/>
</StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I need to show all this in list view. Also, I need another favour my DateTime type give me both Date and Time I only need the Date.but it not the main issue is the listview
Are you sure that the property names in the model are same as the one's in XAML.
Naming seems to be inconsistent, username is all small while rest of the names start with a capital letter, also Categoryview is not CategoryView in the code?
For date formatting you can use the format option of binding
Text="{Binding Path=Date, StringFormat=dd-MM-yyyy}"
For more formatting options see:
https://blogs.msdn.microsoft.com/vsdata/2009/07/06/customize-format-of-datetime-string-in-wpf-and-winform-data-binding/
Related
Using Visual Studio 2019 + Resharper.
hey guys, i want to add listviews, that show things from objects, which i get from a list.
it looks like this, when i code it manually:
The XAML-Code:
<ListView Margin="43,313,642,29" BorderThickness="2" BorderBrush="Red" x:Name="Module1">
<ListView.ItemTemplate>
<DataTemplate>
<WrapPanel>
<TextBlock Text="Modul"/>
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
</WrapPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and the c# code:
List<Module> somename = pPP_2.Components.Modules.Values.Cast<Module>().ToList();
List<Module> whatevername = new List<Module>(){somename[0]};
Module1.ItemsSource = whatevername;
The Modules i refer to have several properties, and the {somename[0]} just gets the first of them and puts it in the list.
So basically my question:
How can i create such xaml code using c#? I want to create a listview like this for each element in my list. i DonĀ“t want to create them manually but let the code do it for me.
thinking about this for days now and would love to get some help here.
Thanks,
IRezzet.
P.S. You can basically ignore the special list i created there. The question should work for every List.
You could use an ItemsControl with a ItemTemplate that renders a ListView that has an ItemTemplate rendering the listview-items. If this gets too complex, consider seperating this into a usercontrol to make it more generic.
The XAML would look something like this:
<ItemsControl x:Name="DynamicGrid">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ListView BorderThickness="2" ItemsSource="{Binding SubChildren}" BorderBrush="Red">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You will need two Model types for this
// And an instance variable
public ObservableCollection<Outer> Lists { get; } = new ObservableCollection<Outer>();
public class Outer
{
public ObservableCollection<Inner> SubChildren { get; } = new ObservableCollection<Inner>();
}
public class Inner
{
public string Name { get; set; }
}
I used this code to seed for testing:
for (int i = 0; i < 10; i++)
{
var o = new Outer();
for (int k = 0; k < 10; k++)
{
o.SubChildren.Add(new Inner() { Name = "ID: "+k });
}
Lists.Add(o);
}
DynamicGrid.ItemsSource = Lists;
I have a <List> that adds and removes elements by calling a modal from a <Button> as shown in the figure.
When lifting the modal, I show the user the elements that can be associated to the main list and also indicate with a <Switch> if these elements are added or not, with the objective that when pressing the switch add or remove elements from the main list
The problem is that when the modal is lifted, the method that adds and deletes elements to the list is executed and every time I raise the modal, my records are duplicated, as shown in the figure
This is due to the fact that when lifting the modal, the method that adds or removes chemicals is executed, this is called every time the property value that is binded to the <Switch> in the view changes
Why is this happening? How can I avoid it?
Then I present my code ...
MODAL.XAML:
<StackLayout
BindingContext="{Binding AgregarSustancia}">
<ListView
ItemsSource="{Binding ListaSustancias}"
SelectedItem="{Binding SelectedSustancia}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<StackLayout Orientation="Vertical">
<Label Text="{Binding NombreSustancia}"
HorizontalOptions="FillAndExpand"
VerticalOptions="CenterAndExpand"/>
</StackLayout>
<Switch
OnColor="{StaticResource das.color.verde}" HorizontalOptions="EndAndExpand"
VerticalOptions="Start"
IsToggled="{Binding SustanciaAsociada, Mode=OneWay}">
</Switch>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<StackLayout/>
AGREGARSUSTANCIA.CS:
bool sustanciaAsociada;
[JsonProperty(PropertyName = "chemicalIsAssociateWithInstallation")]
public bool SustanciaAsociada
{
get
{
return sustanciaAsociada;
}
set
{
if (value != sustanciaAsociada)
{
sustanciaAsociada = value;
AsociarDesasociar(sustanciaAsociada);
}
}
}
//METHOD THAT ADDS OR ELIMINATES DEPENDING ON THE VALUE OF THE PARAMETER
private async void AsociarDesasociar(bool sustanciaAsociada)
{
//ADD TO LIST
if (sustanciaAsociada)
{
}
else //REMOVE TO LIST
{
}
}
Then my ViewModel that fills the modal list
VIEWMODEL.CS: (MODAL)
#region Constructor
public AgregarSustanciaViewModel(ObservableCollection<AgregarSustancia> listaAgregarSustancia)
{
navigationService = new NavigationService();
ListaSustancias = new ObservableCollection<AgregarSustancia>();
listaSustanciasAux = new List<AgregarSustancia>(listaAgregarSustancia);
ListaSustancias = listaAgregarSustancia;
}
#endregion
How can I prevent the method AsociarDesasociar() in the Get-Set property of the Switch from executing the modal? How can I encapsulate this method?
Any help for me?
create a bool InitComplete and initialize it to false. This will prevent AsociarDesasociar from executing before initialization is complete
if (value != sustanciaAsociada)
{
sustanciaAsociada = value;
if (InitComplete) {
AsociarDesasociar(sustanciaAsociada);
}
}
after your class has finished whatever initialization is required, then set InitComplete = true
This is my .xml file - part of listview, where the labels get the data from API. When I click one item I need to get its value of Title and/or Date.
ListView x:Name="listViewStories" Margin="12,0,12,0">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout Orientation="Horizontal">
<Label x:Name="titleOfStory"
Text="{Binding Title}"
TextColor="Black"
FontSize="20"
WidthRequest="180">
</Label>
<Label x:Name="dateOfStory"
Text="{Binding Date}"
TextColor="Black"
FontSize="20"
WidthRequest="180"></Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
and this is my .cs file which I used just as an example the DisplayAlert code so I can get the value, I tried different methods but I couldn't find a solution:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ReadYourPastPage : ContentPage
{
HttpClient client = new HttpClient();
string _ID;
public ReadYourPastPage(string id)
{
InitializeComponent();
_ID = id;
GetStories();
listViewStories.ItemTapped += ListViewStories_ItemTapped;
}
private void ListViewStories_ItemTapped(object sender, ItemTappedEventArgs e)
{
DisplayAlert("I need here to show Title or Date ->", e.Item.ToString() , "Cancel");
}
public async void GetStories()
{
var response = await client.GetStringAsync(returnJSON.GetURL() +
"index.php?IDuser=" + _ID +
"&getStories");
var stories = JsonConvert.DeserializeObject<List<Story>>(response);
listViewStories.ItemsSource = stories;
}
}
The ItemTapped and ItemSelected events give you back the Binding Context associated with the current Listview Cell. I would suggest using the ItemSelected event instead of the ItemTapped. In the event you can use the below code to get your object:
private void ListViewStories_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
// This line null checks the object and also gives you a reference
if (e.SelectedItem is Story story)
{
DisplayAlert($"Title -> {story.Title} Date -> {story.Date}", "Cancel");
// Deselect the cell that was tapped
listViewStories.SelectedItem = null;
}
}
You can't reference the ViewCell in your .cs code behind. You can only access the Binding Context
So I have a customised GridView with a data template that contains a TextBox and is populated by a list of a custom class called Player. I need to be able to retrieve both the instance of Player and the text in the TextBox and save them to a new custom class called Score.
<GridView x:Name="gridScore" ItemsSource="{x:Bind PlayerList}" IsItemClickEnabled="True">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Player">
<StackPanel Orientation="Horizontal">
<TextBox x:Name="txtbxGridScore" TextChanged="txtbxGridScoreChangedEventHandler" />
<Image Source="{x:Bind ProfilePicture}"/>
<StackPanel VerticalAlignment="Center">
<TextBlock Text="{x:Bind FullName}" />
<TextBlock Text="{x:Bind Alias}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<Button x:Name="buttonSave" Content="Save Scores" Style="{StaticResource BarButtonStyle}" Click="buttonSave_Click"/>
I come from a web-based Java background so this is a little bit new to me but it seems like it should be a fairly simple exercise.
Initially, I tried iterating through the GridView upon a Button Click and grabbing each Player item along with the TextBox Text and saving them to a List<> of Score, however, getting the TextBox value proved troublesome.
I then tried initialising a page scope List<> of Score and simply updating it each time the TextBox value was changed, however, I wasn't able to make this work either.
A solution for either approach will work fine for my purposes. Any input is appreciated!
If I correctly understood you this is one of the way to resolve your problem.
So let's assume that your model class Player have this structure:
public class Player {
public int PlayerID { get; set; }
public string ProfilePicture { get; set; }
public string FullName { get; set; }
public string Alias { get; set; }
public float PlayerScore { get; set; } // To store textbox value
}
So you can resolve this by using two way binding.
XAML part will look something like this:
<GridView x:Name="gridScore"
ItemsSource="{x:Bind PlayerList}"
IsItemClickEnabled="True">
<GridView.ItemTemplate>
<DataTemplate x:DataType="data:Player">
<StackPanel Orientation="Horizontal">
<TextBox x:Name="txtbxGridScore"
Text="{x:Bind PlayerScore, Mode=TwoWay}" />
<Image Source="{x:Bind ProfilePicture}" />
<StackPanel VerticalAlignment="Center">
<TextBlock Text="{x:Bind FullName}" />
<TextBlock Text="{x:Bind Alias}" />
</StackPanel>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<Button x:Name="buttonSave"
Content="Save Scores"
Click="buttonSave_Click" />
I have initialized your PlayerList with some dummy data like this:
PlayerList = new ObservableCollection<Player>() {
new Player() {
FullName = "Player A", Alias = "AAA"
},
new Player () {
FullName = "Player B", Alias = "BBB"
}
};
As you can see in XAML I am binding your text box with PlayerScore property of Player model.
When I run this App I get screen like this:
I will input some data into TextBox and click Save button:
When I click on Save it will trigger the event that you wrote in Button part
In that event I have one foreach loop that will iterate through the list and one breakpoint and as you can see on first item "Player A" the PlayerScore value is 10:
Now you can find your players with some ID property or with some other way that you want. This is the most simple way to accomplish what you want.
Remark: This could be solved in a better way using MVVM pattern and other stuff but as you mentioned you are beginner so maybe it is better for you to solve it like this and after that go with more advanced technique. Hope that this was helpful for you.
I'm using an ObservableCollection<BarcodeInfo> as ItemsSource of a ListView to generate ViewCells. A Cell contains 2 Labels and a ZXingBarcodeImageView with bindings to my BarcodeInfo-class, everything works as expected.
Now I've to remove several cells from the ListView, but as soon as I try to do so, I get the following Exception from the ZXingBarcodeImageView
System.ArgumentException: Found empty contents
Here's my XAML
<ListView RowHeight="50">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="3*" />
</Grid.ColumnDefinitions>
<zxing:ZXingBarcodeImageView
BarcodeFormat="{Binding Format}"
BarcodeOptions="{Binding Options}"
BarcodeValue="{Binding Text}"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand"
Margin="5"
Grid.Column="0"/>
<StackLayout Grid.Row="0" Grid.Column="1"
Spacing="0" VerticalOptions="CenterAndExpand">
<Label Text="{Binding Text}"
LineBreakMode="TailTruncation"
VerticalOptions="End"/>
<Label Text="{Binding Format}"
VerticalOptions="End"
LineBreakMode="TailTruncation"/>
</StackLayout>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
And the Class for ObservableCollection<BarcodeInfo> _barcodeCollection; in the of the ListView
public class BarcodeInfo
{
public string Text
{ get; set; }
public string Detail
{ get; set; }
public BarcodeFormat Format
{ get; set; }
public EncodingOptions Options
{ get; set; }
}
The Exceptions happens as soon as I try
_barcodeCollection.RemoveAt(i);
I've implemented the INotifyPropertyChanged and tried to set all properties to null which works without exception, but the ZXingBarcodeImageView is not clearing the barcode-image and the Exception is still thrown if I try to remove the Item from the Collection. I'm at a point where I've no more ideas.
I hope anybody can help me.
Update
Because the i seems to be confusing here's the loop I'm using it
for (int i = 0; i < _barcodeCollection.Count; i++)
{
var response =
await _serverUrl.PostUrlEncodedAsync(
new { barcode = _barcodeCollection[i].Text })
.ReceiveString();
if (string.Equals(response, "ok", StringComparison.OrdinalIgnoreCase))
{
percentage += progressSteps;
_barcodeCollection.RemoveAt(i); //EXCEPTION!!!
i--; // index must be checked twice else one element will be skipped
await UploadProgress.ProgressTo(percentage, 250, Easing.Linear);
}
}
Not a straightforward solution, but the easiest workaround I've found was to provide FallbackValue when binding BarcodeValue
<forms:ZXingBarcodeImageView BarcodeFormat="{Binding Format}"
BarcodeValue="{Binding Content, FallbackValue='1'}" />
I have managed to identify the cause of the problem, it is a side effect of the way that the ListView is refreshed when the elements are removed and the ListViewCachingStrategy is set to RetainElement (the default).
The custom renderer OnElementPropertyChanged is called when the items are removed from the collection, and the regenerate() method in the ZXing custom renderer crashes.
This can be solved by setting the ListViewCachingStrategy to RecycleElement, this will work with Android, however there is still a problem with iOS 10, which does not correctly support a listview with ListViewCachingStrategy set to RecycleElement, iOS 10 currentlly works only with ListViewCachingStrategy set to RetainElement, this can be accommodated if you create a custom control in your portable code eg:
public class MyZXingBarcodeImageView : ZXingBarcodeImageView
{
//THERE IS NO CODE REQUIRED HERE
}
And then create your own custom renderer based on the ZXing source, but replace the void regenerate() method with the following:
void regenerate()
{
if(formsView != null && !string.IsNullOrWhiteSpace(formsView.BarcodeValue) )
{
var writer = new ZXing.Mobile.BarcodeWriter();
if(formsView != null && formsView.BarcodeOptions != null)
writer.Options = formsView.BarcodeOptions;
if(formsView != null && formsView.BarcodeFormat != null)
writer.Format = formsView.BarcodeFormat;
var value = formsView != null ? formsView.BarcodeValue : string.Empty;
Device.BeginInvokeOnMainThread(() =>
{
var image = writer.Write(value);
imageView.Image = image;
});
}
}
The change is in the very first If statement, changing from testing for null string to string.IsNullOrWhiteSpace
You do NOT have to create a custom renderer for Android if you use ListViewCachingStrategy set to RecycleElement, the base renderer for ZXingBarcodeImageView will be used without error.