How to refresh listview after save date in my list<Product> - xamarin.forms

I am using popup for to save dates in list and last I wanna show the dates in listview

You Can Make Use Of Two Way Binding By Implementing INotifypropertychanged.
If you Want to implement in code behind you can do it in this way
OnButtonDateAdd()
{
listview.BeginRefresh();
var filter = get the new data
listview.ItemsSource = filter;
listview.EndRefresh();
}
}
Hope this solves your issue

Related

Devexpress ASPxGridView New Row Disabled

I have code like this with devexpress ASPxGridView. Everything goes well, but when I try to add new row, new row's textbox is disabled...
I have KeyFieldName set.
void BindGrid()
{
var AnnObj = SearchBarBanners.Select(i => new
{
Caption = i.Attribute("caption").Value,
ID = i.Attribute("id").Value, // this is generated by Guid
}).ToList();
ImagesGrid.DataSource = AnnObj;
ImagesGrid.DataBind();
}
I can suggest you two things without grid markup:
1. Call BindGrid method in Page_Init
2. If your datasource initially returns zero rows, grid won't be able to determine type of objects that will be rendered in grid. You need to use ASPxGridView.ForceDataRowType in order to solve this problem.
Use recommendations from the Q392961 DX Article to resolve this issue.

How to keep a list from scrolling on dataProvider refresh/update/change?

I have a simple list and a background refresh protocol.
When the list is scrolled down, the refresh scrolls it back to the top. I want to stop this.
I have tried catching the COLLECTION_CHANGE event and
validateNow(); // try to get the component to reset to the new data
list.ensureIndexIsVisible(previousIndex); // actually, I search for the previous data id in the IList, but that's not important
This fails because the list resets itself after the change (in DataGroup.commitProperties).
I hate to use a Timer, ENTER_FRAME, or callLater(), but I cannot seem to figure out a way.
The only other alternatives I can see is sub-classing the List so it can catch the dataProviderChanged event the DataGroup in the skin is throwing.
Any ideas?
Actually MUCH better solution to this is to extend DataGroup. You need to override this.
All the solutions here create a flicker as the scrollbar gets resetted to 0 and the it's set back to the previous value. That looks wrong. This solution works without any flicker and the best of all, you just change DataGroup to FixedDataGroup in your code and it works, no other changes in code are needed ;).
Enjoy guys.
public class FixedDataGroup extends spark.components.DataGroup
{
private var _dataProviderChanged:Boolean;
private var _lastScrollPosition:Number = 0;
public function FixedDataGroup()
{
super();
}
override public function set dataProvider(value:IList):void
{
if ( this.dataProvider != null && value != this.dataProvider )
{
dataProvider.removeEventListener(CollectionEvent.COLLECTION_CHANGE, onDataProviderChanged);
}
super.dataProvider = value;
if ( value != null )
{
value.addEventListener(CollectionEvent.COLLECTION_CHANGE, onDataProviderChanged);
}
}
override protected function commitProperties():void
{
var lastScrollPosition:Number = _lastScrollPosition;
super.commitProperties();
if ( _dataProviderChanged )
{
verticalScrollPosition = lastScrollPosition;
}
}
private function onDataProviderChanged(e:CollectionEvent):void
{
_dataProviderChanged = true;
invalidateProperties();
}
override public function set verticalScrollPosition(value:Number):void
{
super.verticalScrollPosition = value;
_lastScrollPosition = value;
}
}
I ll try to explain my approach...If you are still unsure let me know and I ll give you the source code as well.
1) Create a variable to store the current scroll position of the viewport.
2) Add Event listener for Event.CHANGE and MouseEvent.MOUSE_WHEEL on the scroller and update the variable created in step 1 with the current scroll position;
3) Add a event listener on your viewport for FlexEvent.UpdateComplete and set the scroll position to the variable stored.
In a nutshell, what we are doing is to have the scroll position stored in variable every time user interacts with it and when our viewport is updated (due to dataprovider change) we just set the scroll position we have stored previously in the variable.
I have faced this problem before and solved it by using a data proxy pattern with a matcher. Write a matcher for your collection that supports your list by updating only changed objects and by updating only attributes for existing objects. The goal is to avoid creation of new objects when your data source refreshes.
When you have new data for the list (after a refresh), loop through your list of new data objects, copying attributes from these objects into the objects in the collection supporting your list. Typically you will match the objects based on id. Any objects in the new list that did not exist in the old one get added. Your scroll position will normally not change and any selections are usually kept.
Here is an example.
for each(newObject:Object in newArrayValues){
var found:Boolean = false;
for each(oldObject:Object in oldArrayValues){
if(oldObject.id == newObject.id){
found = true;
oldObject.myAttribute = newObject.myAttribute;
oldObject.myAttribute2 = newObject.myAttribute2;
}
}
if(!found){
oldArrayValues.addItem(newObject);
}
}
My solution for this problem was targeting a specific situation, but it has the advantage of being very simple so perhaps you can draw something that fits your needs from it. Since I don't know exactly what issue you're trying to solve I'll give you a description of mine:
I had a List that was progressively loading data from the server. When the user scrolled down and the next batch of items would be added to the dataprovider, the scrollposition would jump back to the start.
The solution for this was as simple as stopping the propagation of the COLLECTION_CHANGE event so that the List wouldn't catch it.
myDataProvider.addEventListener(
CollectionEvent.COLLECTION_CHANGE, preventRefresh
);
private function preventRefresh(event:CollectionEvent):void {
event.stopImmediatePropagation();
}
You have to know that this effectively prevents a redraw of the List component, hence any added items would not be shown. This was not an issue for me since the items would be added at the end of the List (outside the viewport) and when the user would scroll, the List would automatically be redrawn and the new items would be displayed. Perhaps in your situation you can force the redraw if need be.
When all items had been loaded I could then remove the event listener and return to the normal behavior of the List component.

Help with containers

I am using view stack...so when view change like when we move from one page to another hide event is dispatched.So i am saving the information of last page in hide event before i go to next page.but thing is that if i change nothing still change on view hide event is invoked nd call go to backend...i just want do call only if sumthing change in the view..like sum text value...So i have two options
use event listener on each component if sumthing change its make the flag true...nd hide event check, if flag is true send call to backend.
event listener at container level ..if sumthing change in child componenet through bubbling container knows if sum event is dispatched.nd makes the flag true.
I have doubt with container...
Can i use container, and how?
Reason why I can't use container?
What are the pros and cons either way?
I would recommend using a dataProvider with the ability to compare them. For instance, if you are changing things with textinputs, you could basically do something like this:
[Bindable]
private var myDataProvider:Object = new Object();
private function creationCompleteHandler():void {
myDataProvider.updated = false;
myDataProvider.defaultValue = 'default';
myDataProvider.defaultValueTwo = 'default';
}
etc.
Then, in your mxml, you can have something like this:
<mx:TextInput id="myText" text="{myDataProvider.defaultValue}" change="myDataProvider.defaultValue=myText.text; myDataProvider.updated=true;" />
Lastly, in your hide event, you can do the following:
private function hideEventHandler( event:Event ):void {
if( myDataProvider.updated ){
// Call your RemoteServices (or w/e) to update the information
}
}
This way, when anything changes, you can update your dataProvider and have access to the new information each time.
Hope this helps!
I've used an approach similar to your first option in a couple of my past projects. In the change event for each of my form's controls I make a call to a small function that just sets a changesMade flag to true in my model. When the user tries to navigate away from my form, I check the changesMade flag to see if I need to save the info.
Data models are your friend!
If you get in the habit of creating strongly typed data models out of your loaded data, questions like this become very basic.
I always have a key binding set to generate a code snipit similar to this...
private var _foo:String;
public function get foo():String
{
return _foo;
}
public function set foo(value:String):void
{
if(_foo == value)
return;
var oldVal:String = _foo;
_foo = value;
this.invalidateProperty("foo", oldVal, value);
}
If your data used getters/setters like this, it would be very easy to validate a change on the model level, cutting the view out of the process entirely.

Flex/AS3 Using Multiple Item Renderers In a List

I'm trying to have multiple item renderers in a list, as I have several different types of objects that I want to display. I tried creating a new class that extends ListBase, and adding override public function createItemRenderer with my code within this function. I then instantiate the new class and give it my array of data as its dataProvider, but createItemRenderer is never called within my new class, can anyone help me please?
Thank you
I managed to solve this by extending List instead of ListBase, so thanks shakakai for making me think about that :)
Incase anyone else has a similar problem here is what my code looks like:
public class MultipleRenderersList extends List
{
override public function createItemRenderer(data:Object):IListItemRenderer
{
if (data is Type1)
{
return new Type1Component;
}
else if (data is Type2)
{
return new Type2Component;
}
return null;
}
I've dealt with this in the past by creating a single item renderer that can handle different types of data. There are a few ways to do this, such as changing states based on data type, or using a ViewStack that switches based on data type, or using actionscript to create/add a sub-component to display the data appropriately. Just override the set data method on your item renderer and switch up the components as necessary. Hope that helps.

Flex DataGrid: Programmatically Highlighting Rows

This seems like something that should be painfully simple, but I can't even find how to loop through rows in a Flex DataGrid.
Basically what I'm trying to accomplish is something like this pseudo-code:
for each(var row:Row in myDataGrid.Rows)
{
if(row.DataObject.Number == 1)
{
row.Color = Red;
}
}
I'm trying to have a Save button that upon being clicked either processes the save, or highlights the invalid rows and pops up a message telling the user why the rows are invalid. Because of some other complexities, I am not able to validate each row as it is entered. Any help is appreciated! Thanks.
Data grids are intended to be driven by their data rather than manipulated directly. One way to accomplish what you are trying to do is to add some sort of property, say "valid", to the data objects in your provider and add code to the renderer to alter its appearance based on the state of "valid". In that way you could loop through the objects in your data provider and set the "valid" property based on your validation check, which would cause the rows in the data grid to change their appearance automatically.
Hope that helps.
Try something like this:
for each(var o:Object in myDataGrid.dataProvider)
{
if(o.Number == 1) {
myDataGrid.selectedItems.push(o);
}
}
In your mxml you can set the selectionColor of the datagrid to red. See: http://blog.flexexamples.com/2008/02/19/setting-the-selection-color-and-selection-disabled-color-for-a-row-in-the-flex-datagrid-control/
Let me know if this works for you!
I am not sure you can do it on the data grid itself, but if you have an item renderer for each of the items, you can have your highlighting logic there.
basically, you define your datagrid's item renderer class:
<mx:DataGrid itemRenderer="ItemRendererClass"(...) ></mx:DataGrid>
and then you define the class "ItemRendererClass" as implementing IDataRenderer:
implements="mx.core.IDataRenderer"
This is a simplistic explanation, assuming you can figure out how to do this on yourself :)
I achieved this by overriding the set data. I have provided the sample code below.
override public function set data(value:Object):void
{
super.data=value;
if(value!=null && value.hasOwnProperty("state") && value.state == "Final State"){
setStyle("color", 0xb7babc);
}else{
setStyle("color", 0x000000);
}
this.selectable=false;
super.invalidateDisplayList();
}

Resources