I have a ListView of custom components that receive a boolean #Input() property which is responsible of displaying some parts of the template.
This is the ListView :
<ListView [items]="photos">
<ng-template let-item="item">
<app-post [photo]="item" [displayInfo]="display"></app-post>
</ng-template>
</ListView>
The display variable is set to false.
And this is the app-post template :
<StackLayout *ngIf="displayInfo" verticalAlignment="center">
....
</StackLayout>
Where displayInfo is the input property.
Inside the app-post component I have logic that changes the displayInfo value to true.
I noticed however that the ListView only creates a couple of components and than reuses them as scrolling down.
This causes the following (example) scenario :
List of 5 app-post components, all with displayInfo to false
Click on 1st app-post component sets displayInfo to true
3d and 5th app-post components have already displayInfo set to
true
How can I avoid this behaviour and have all custom components with the property set to the value specified with in the listview?
The NativeScript ListView is virtualized and is using recycling for its cells which are causing your issue as you are expecting the custom components to be as originally created in your list while, in fact, they are part of list cells that are being reused.
The solution is to introduce the displayInfo boolean as a part of your items model. Here is a similar solution explained for TypeScript project but the very same concept could be used in Angular based project
Related
I am using the multi-platform Xamarin forms, and I want to be able to click a button and select all the items inside a collectionview.
I have :
<CollectionView x:Name="collectionList" SelectionMode="Multiple"
SelectionChanged="RowSelected"
ItemsSource="{Binding ContentList}">
and inside the cs file:
ObservableCollection ContentList = //list made in an earlier method, this is confirmed working
collectionList.SelectedItems= ContentList; //executes on the button click event
However that does not work as SelectedItems requires an IList which does not accept normal List or ObservableCollection. I also tried setting the SelectedItems to collectionList.ItemsSource (the collectionview source) but that gave the same type error which is Cannot implicitly convert type 'System.Collections.Generic.List<object>' to 'System.Collections.Generic.IList<object>'
What I have currently working is that the collectionview populates with data, and multiple items can be manually selected by the user. This returns me the items that were tapped. I cannot get the view to select everything programmatically though.
I have searched all over and I haven't seen any posts trying to do this, what is the best approach to making a "select all" button for collectionviews?
Edit: The problem was that my list had a defined class as the list type and it needed to be of type object as listed in the accepted answer below
I just tried this and it works
collectionList.SelectedItems = new ObservableCollection<object>(ContentList);
there are undoubtedly other approaches, but not that I can think of on a Sunday afternoon
I have a ViewCharacter page that has a View Model (CharacterViewModel) as its DataContext, in that CharacterViewModel I have an ObservableCollection of WeaponViewModel that a ListBox is using as an ItemSource. The ListBox's DataTemplate contains a UserControl that is designed for the WeaponViewModels in the parent page's View Model's ObservableCollection. I need to bind a CommandParameter of a button in the UserControl to a property on the Parent page's view model (CharacterViewModel). I've tried using {Binding DataContext.TargetProperty, RelativeSource={RelativeSource TemplatedParent}} with no success and am at a loss of what to do without outright breaking all MVVM patterns.
Windows Phone 7 lacks a relative source binding. I have created a Silverlight implementation here:
http://www.scottlogic.co.uk/blog/colin/2009/02/relativesource-binding-in-silverlight/
But for WP7, where performance is critical, I would avoid using it!
I would instead recommend making the relationship between CharacterViewModel and WeaponViewModel bi-directional. In other words, add a Parent property to WeaponViewModel which will be a reference to the owning CharacterViewModel. You can then bind to properties on CharacterViewModel via this property.
<TextBlock Text="{Binding Name}"/>
Binding works fine when I first navigate to a page containing the code above. Then I navigate forward to a page that that makes changes to the model (the Name property) and navigate back (with back key). The Text property, however, is still displaying the old value. How can I force the bound value to update on back navigation.
Make sure that your model implements INotifyPropertyChanged and that the PropertyChanged event is firing within the setter of Name
Using MVVM Light I have a listbox databound to a collection of several items.
One of the items is the selected one.
With this code it works perfectly and ViewModel structures are updated correctly:
<Name="listBox1"
ItemsSource="{Binding Path=Models}"
SelectedItem="{Binding Path=csProfile.Model, Mode=TwoWay}">
My problem is that when I enter the page if the selected Item is not in the first items it is not visible and the user does not know what was the previous selection.
How could I force the Listbox to always show the Selected Item?
Possibly via properties or Binding.
M
There's no property you can bind to to set what's visible. Instead call ScrollToVerticalOffset() on the ScrollViewer inside the ListBox.
I think you are looking for the ScrollIntoView method. A similar topic was discussed here:
Automatic Scrolling in a Silverlight List Box
The API reference is here: http://msdn.microsoft.com/en-us/library/system.windows.controls.listbox.scrollintoview(VS.95).aspx
Calling UpdateLayout() before calling ScrollIntoView on the selected item seems to be necessary.
I have a Listbox with Button and Textblock as ItemTemplate. Button has an onClick event.
All i want is to get the index of the clicked item, but SelectedIndex property in my ListBox is always -1!
How can I get the index of the clicked item?
The problem is that the Button control is swallowing the mouse events to provide the Click behavior, so the ListBox never receives any events to tell it that the selection has changed.
As #Alexander suggests, you could use an MVVM-style approach with commands to handle the action in a view model and pass the data context as the parameter.
Alternatively, you could replace the Button with any other layout control and either use the gesture service from the Silverlight Toolkit or use the regular MouseLeftButtonUp event. In either instance, the mouse events will bubble up and enable the ListBox to handle selection.
You might want to actually select something in your listbox then :p
If you want to get data object associated with current ListItem use RouteCommand. Here is example
<ListView.ItemTemplate>
<DataTemplate>
<Button Margin="5,0" Command="{StaticResource ButtonCommand}"
CommandParameter="{Binding}">
</DataTemplate>
<ListView.ItemTemplate>
You need also define Command at least in ListView.Resources
<RoutedCommand x:Key="ButtonCommand"/>
And then setup CommandBinding like this
<ListView.CommandBindings>
<CommandBinding Command="{StaticResource ButtonCommand}" Executed="Button_Click"/>
</ListView.CommandBindings>
In the end write handler
Button_Click(object sender, ExecutedRoutedEventArgs e)
{
e.Parameter// object that you Specified in CommandParameter
}
In advance you can use any MVVM framework, define all command and commands logic in model and then just bind this commands to corresponding elements.