sfChart reset data for graph - xamarin.ios

I have a graph in a 'detail' view. this is accessed when an item is chosen in a tableview. the first graph is correct, but when I pick another item in the table, it still shows the first graph. I enabled ListenPropertyChange = true and raispropertychanged it twice.
view(viewdidload):
SFChart chart = new SFChart();
chart.Frame = this.headerview.Frame;
//Adding Primary Axis for the Chart.
SFCategoryAxis primaryAxis = new SFCategoryAxis();
chart.PrimaryAxis = primaryAxis;
//Adding Secondary Axis for the Chart.
SFNumericalAxis secondaryAxis = new SFNumericalAxis();
chart.SecondaryAxis = secondaryAxis;
SFLineSeries series = new SFLineSeries()
{
XBindingPath = "timestamp",
YBindingPath = "price_btc",
ListenPropertyChange = true
};
series.EnableTooltip = true;
chart.Series.Add(series);
set.Bind(series).For(s => s.ItemsSource).To(vm => vm.CoinHistory);
set.Apply();
viewModel(init):
CoinHistory = new ObservableCollection<ChartDataModel>(_CoinHistoryGraph.Select(x => new ChartDataModel(float.Parse(x.price_btc), x.timestamp)));
RaisePropertyChanged(() => CoinHistory);
ViewModel properties:
private ObservableCollection<ChartDataModel> _CoinHistory;
public ObservableCollection<ChartDataModel> CoinHistory
{
get
{
return _CoinHistory;
}
set
{
_CoinHistory = value;
RaisePropertyChanged(() => CoinHistory);
}
}

How do you pass your model data to the details view? According to your descriptions, the first ViewModel should hold the whole data. When user click one cell, the tableView source's SelectionChangedCommand event will trigger. Normally we bind this command to the corresponding ViewModel's command, then we can configure the push and pass the parameters there.
Here is my bind in the first view which contains a UITableView:
var set = this.CreateBindingSet<FirstView, FirstViewModel>();
set.Bind(source).For(s => s.ItemsSource).To(vm => vm.ItemsGroup);
set.Bind(source).For(s => s.SelectionChangedCommand).To(vm => vm.ShowDetailsCommand);
set.Apply();
When user click one cell in the TableView, ShowDetailsCommand will fire in the FirstViewModel:
private readonly Lazy<IMvxNavigationService> _navigationService = new Lazy<IMvxNavigationService>(Mvx.Resolve<IMvxNavigationService>);
private MvxCommand<Item> showDetailsCommand;
public ICommand ShowDetailsCommand
{
get
{
return showDetailsCommand ?? (showDetailsCommand = new MvxCommand<Item>(showDetails));
}
}
async void showDetails(Item item)
{
// This item is bound to the ItemsSource through ItemsGroup
await _navigationService.Value.Navigate<SecondViewModel, Item>(item);
}
Then the second ViewModel can accept this item via:
public class SecondViewModel : MvxViewModel<Item>
{
private List<CoinHistoryModel> _CoinHistory;
public List<CoinHistoryModel> CoinHistory
{
get
{
return _CoinHistory;
}
set
{
_CoinHistory = value;
RaisePropertyChanged(() => CoinHistory);
}
}
public override void Prepare(Item parameter)
{
CoinHistory = parameter.SingleCoinHistory;
}
}
At last the details view will show the CoinHistory, if you have successfully bound it to the second view model.
Here is my demo for you referring to.

I was not able to replicate the issue you have stated here, instead I have prepared a sample based on your requirement and you can find the sample from the below link.
Sample
If this does not resolve your query, can you revert me back with more details.
Hope this helps
Note: I work for Syncfusion.

Related

Is there a way to make custom lookup on dialog field on Microsoft Dynamics 365?

I have problems with my dialog field. I have button that opens dialog tab with field. It was supposed to show on that field lookup exact records(i guess i need select there by one field value). Right now i have this code:
DialogField Journal = dialog.addField(extendedTypeStr(JournalId));
This dialog line adds a field with all values on that EDT. I have 3 journal types - NEW, UPDATE, DELETE. Right now on that field lookup it shows me all 3 journal types. I want to make custom lookup that shows exact type , example - if i click that button on journal that has type "NEW", then it should show only "NEW" type of journal types on lookup. I heard there is something like dialog.addLookup or something. Can someone help me?
You already added your dialog field (in the dialog() method). Now add the dialogRunPost() method that is executed after the form GUI is initialized. At that point you can fetch the underlying FormStringControl behind the dialog field. Subscribing to the FormStringControl.OnLookup event allows you to override the lookup.
I did not have some journal data available, so I created a similar example with customers. My example dialog (MyDialog) takes a source customer (customerCaller) and shows a dialog with a custom lookup that only shows customers with the same customer group.
My example is also a standalone, runnable class and is not called from a form. Comments have been added to indicate where this affects the code.
Full example
public class MyDialog extends Runbase
{
// fields
protected Args args;
protected CustTable customerCaller;
protected DialogField dfCustomerId;
// construct
public static MyDialog newArgs(Args _args)
{
MyDialog ret = new MyDialog();
ret.args = _args;
return ret;
}
// initialize
public boolean init()
{
boolean ret = super();
// validate and fetch caller
if (args.record() && args.record().TableId == tableNum(CustTable))
//if (args.caller() && args.caller().dataset() == tableNum(CustTable)) --> when called from form
{
customerCaller = args.record();
//customerCaller = args.caller().record();
}
else
{
throw error(Error::missingRecord('My Dialog'));
}
return ret;
}
// build dialog
public Object dialog()
{
Dialog ret = super();
// optional reference to visualize the input
ret.addText('Caller customer group = ' + customerCaller.CustGroup);
// add field
dfCustomerId = ret.addField(extendedTypeStr(CustAccount)); // default lookup = all CustTable.AccountNum values
return ret;
}
public void dialogPostRun(DialogRunbase dialog)
{
super(dialog);
// subscribe to lookup event
FormStringControl fscCustomerId = dfCustomerId.control();
fscCustomerId .OnLookup += eventhandler(this.customerId_OnLookup);
}
// custom lookup for customer id
protected void customerId_OnLookup(FormControl _sender, FormControlEventArgs _e)
{
// cancel default
FormControlCancelableSuperEventArgs eventArgs = _e;
eventArgs.CancelSuperCall();
// define lookup query (list all customers with same customer group as input customer)
Query query = new Query();
QueryBuildDataSource qbds = SysQuery::findOrCreateDataSource(query, tableNum(CustTable));
SysQuery::findOrCreateRange(qbds, fieldNum(CustTable, CustGroup)).value(SysQuery::value(customerCaller.CustGroup));
// do lookup
SysTableLookup lookup = SysTableLookup::newParameters(tableNum(CustTable), _sender);
lookup.parmQuery(query);
lookup.addLookupfield(fieldNum(CustTable, AccountNum), true);
lookup.addLookupfield(fieldNum(CustTable, CustGroup));
lookup.performFormLookup();
}
// run dialog
public static void main(Args _args)
{
// I am running this dialog directly (not from a form), generating some random input
CustTable customer;
select firstonly customer where customer.CustGroup != '';
_args.record(customer);
// end of random input
MyDialog md = MyDialog::newArgs(_args);
md.init();
if (md.prompt())
{
md.run();
}
}
}
Result

How to bind Map/Image in a List with Click event?

I want to bind map with a field and its click event as well, which will take it to a MvxCommand and show some MapViewModel.
[Register("HoursEntryCell")]
public class HoursEntryCell : MvxTableViewCell
{
public HoursEntryCell()
{
CreateLayout();
InitializeBindings();
}
public HoursEntryCell(IntPtr handle)
: base(handle)
{
CreateLayout();
InitializeBindings();
}
private UILabel hours;
private UIImageView imageView;
private UILabel jobName;
private MKMapView location;
private void CreateLayout()
{
jobName = new UILabel(new RectangleF(10, 10, 100, 30));
jobName.AdjustsFontSizeToFitWidth = true;
jobName.Lines = 0;
jobName.Font = jobName.Font.WithSize(16);
imageView = new UIImageView(UIImage.FromBundle("pencil.png"));
imageView.Frame = new RectangleF(270, 10,imageView.Image.CGImage.Width, imageView.Image.CGImage.Height);
Accessory = UITableViewCellAccessory.DisclosureIndicator;
location = new MKMapView(new RectangleF(15, 40, 280, 160));
location.AddAnnotation(new MKPointAnnotation()
{
Title = "My Loc",
Coordinate = new CLLocationCoordinate2D(23.0092509, 72.5061084)
});
location.UserInteractionEnabled = false;
salaryLable.Text = "Salary";
hours = new UILabel(new RectangleF(200,200,50,50));
ContentView.AddSubviews(jobName, location, hours,salaryLable, imageView);
}
private void InitializeBindings()
{
this.DelayBind(() =>
{
var set = this.CreateBindingSet<HoursEntryCell, ListViewModel>();
set.Bind(location).To(vm => vm.MyLocation);
set.Bind(hours).To(vm => vm.Salary);
set.Bind(jobName).To(vm => vm.EmployeeName);
set.Apply();
});
}
}
}
I want to achieve something like set.Bind(location).To(vm => vm.GoNextCommand); along with the map (set.Bind(location).To(vm => vm.MyLocation);)
Or How can I bind simple image button click event to a MvxCommand from the list?
How can I go for it?
Need Help.
You'll probably need to do a combination of things to get this to work properly...
1.) Do your binding from the view that has your list view. In the example above how does the cell actually get access to your view model? Look at the example here: https://github.com/MvvmCross/MvvmCross-Tutorials/blob/master/DailyDilbert/DailyDilbert.Touch/Views/ListView.cs#L16
2.) you'll need to probably create custom bindings to handle the map view or it might be similar to this example from Stuart: MvvmCross iOS: How to bind MapView Annotation to jump to another view?

MVVMCross Data Binding after returning from ViewController

I am using MVVMCross 3.2.2 as part of an iOS/Android app. One of my screens has multiple views that are displayed depending upon the selection in a Tab bar like row of buttons. Different data is displayed in each of these these views individual UITableView. The data binding works perfectly.
I also have a menu, that has a "profile" selection. Changing the profile fires an MvxMessage that my HomeView receives and then uses the message to set the ViewModel up to filter the data to be displayed. This all seems to work perfectly and the data is displayed correctly.
If I do something in the HomeView that displays another view using ShowViewModel(). When I return back to the home view the binding no longer works properly when a profile changes is made. The message gets handled, the data gets filtered, but a call to ReloadDataTable on the UITableView does not change the data.
ViewModel
#region Groupings
public IList<Group> Groups{
get { return _groupService.GetAll(); }
}
public void SetupSubGroups(Group group)
{
if (group == null)
{
_groups = new ObservableCollection<Group> ();
if (_profileService.SelectedProfile != null)
{
var grp = _groupService.GetByGroupName (_profileService.SelectedProfile.Name);
if (grp == null)
grp = new Group { Name = _profileService.SelectedProfile.Name };
_groups.Add (grp);
}
}
else
{
var litsOfGroups = _groupService.GetSubGroups (group);
foreach (var grp in litsOfGroups)
_groups.Add (grp);
}
RaisePropertyChanged(() => AvailableGroups);
}
private ObservableCollection <Group> _groups;
public ObservableCollection<Group> AvailableGroups {
get { return _groups; }
}
#endregion
ViewController
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
var groupSource = new GroupTableViewDataSource (TableViewGroups);
TableViewGroups.Source = groupSource;
_localViewModel.SetupSubGroups (null);
_bindingSet = this.CreateBindingSet<HomeViewController, HomeViewModel> ();
_bindingSet.Bind (groupSource).To (vm => vm.AvailableGroups);
_bindingSet.Apply ();
TableViewReportTags.ReloadData ();
NavigationController.NavigationBarHidden = false;
}
private void OnProfileChanged(ProfileChangedMessage message)
{
_localViewModel.SetupSubGroups (null);
TableViewGroups.ReloadData ();
}
private HomeViewModel _localViewModel { get { return ViewModel as HomeViewModel; } }
Any ideas what I can look at, or change would be really useful. I have spend many hours on this, and have made no progress.

How do you Bind an Image to the HighlightedImage-Property of an ImageView?

I'm currently trying to bind two images to an iOS ImageView via MvvmCross.
One should be displayed when the ImageView is in 'default' state, the other one when the ImageView is highlighted.
By the following code I can bind the Image for the default state. But how do I bind the one for 'highlighted' state?
public CategoryCell(IntPtr handle): base(string.Empty, handle)
{
_imageViewLoader = new MvxImageViewLoader(() => this.imageView);
this.DelayBind(() =>
{
var set = this.CreateBindingSet<CategoryCell, MaterialCategory>();
set.Bind(titleLabel).To(materialCategory => materialCategory.Label);
set.Bind(_imageViewLoader).To(materialCategory => materialCategory.ImageActiveUri);
set.Bind(this).For(cell => cell.Selected).To(materialCategory => materialCategory.IsSelected);
set.Apply();
});
}
Another approach if you do not need image loading i.e. for lots of static UX.
You can set up as follows -
_imageView = new UIImageView(UIImage.FromFile("some/image/off.png"))
{
HighlightedImage = UIImage.FromFile("some/image/on.png")
};
And bind it e.g. an "Enabled" Property -
this.DelayBind(() =>
{
var set = this.CreateBindingSet<SomeView, SomeViewModel>();
set.Bind(_imageView).For(v => v.Highlighted).To(vm => vm.Enabled);
set.Apply();
});
And don't forget to add Highlighted to your LinkerPleaseInclude.cs.
Hope this helps
I think the best solution is to introduce an extra property ImageUri. In the setter of your IsSelected you set the ImageUri dependend on the selection state.
ViewModel:
public class MaterialCategory : MvxViewModel
{
//...
public string ImageActiveUri { ... } // call UpdateImageUri() here, too
public string ImageInactiveUri { ... } // call UpdateImageUri() here, too
public string ImageUri { ... }
public bool IsSelected
{
get { return _isSelected; }
set
{
_isSelected = value;
UpdateImageUri();
RaisePropertyChanged(() => IsSelected);
}
}
private void UpdateImageUri()
{
ImageUri = IsSelected ? ImageActiveUri : ImageInactiveUri;
}
}
Binding:
set.Bind(_imageViewLoader).To(materialCategory => materialCategory.ImageUri);
// instead of:
// set.Bind(_imageViewLoader).To(materialCategory => materialCategory.ImageActiveUri);

How to ticker List elements when they are Commands?

If I create a List based on an array of Commands, and the text of some Commands are not entirely shown in the List, although the List preferredWidth is set to the Form preferredWidth, how to ticker them ?
Thank you very much
Add the below class in your midlet class or create a new class file for that:
class TickerRenderer extends DefaultListCellRenderer {
private DefaultListCellRenderer selectedRenderer = new DefaultListCellRenderer(false);
private List parentList;
public TickerRenderer() {
super(false);
}
public boolean animate() {
if (parentList != null && parentList.getComponentForm() != null) {
if (selectedRenderer.isTickerRunning()) {
if (selectedRenderer.animate()) {
parentList.repaint();
}
}
}
return super.animate();
}
public Component getListCellRendererComponent(List list, Object value, int index, boolean isSelected) {
if (isSelected) {
selectedRenderer.getListCellRendererComponent(list, value, index, isSelected);
// sometimes the list asks for a dummy selected value for size calculations and this might
// break the tickering state
if (index == list.getSelectedIndex()) {
if (selectedRenderer.shouldTickerStart()) {
if (!selectedRenderer.isTickerRunning()) {
parentList = list;
list.getComponentForm().registerAnimated(this);
selectedRenderer.startTicker(UIManager.getInstance().getLookAndFeel().getTickerSpeed(), true);
}
} else {
if (selectedRenderer.isTickerRunning()) {
selectedRenderer.stopTicker();
}
}
}
return selectedRenderer;
} else {
return super.getListCellRendererComponent(list, value, index, isSelected);
}
}
}
Use it like this:
List cmdList = new List(cmds);
cmdList.setListCellRenderer(new TickerRenderer());
Try this code, it will show list in dialog box on clicking "Show list" command and will also enable ticker initially. Below is the code which shows how to use the above mentioned class to see ticker in list when list is contained in dialog.
Don't forget to make your list final so that it can be used in inner classes.
form.addCommand(new Command("Show list") { // add command in form and override its actionPerformed method
public void actionPerformed(ActionEvent evt) {
Dialog d = new Dialog() { // create an instance of dialog and make it an inner class so that you can override onShow() method and set focus on list when dialog gets initialized and also can set its index to ur preferred one (here it's 0)
protected void onShow() { // overriding of onShow() method
list.requestFocus(); // set focus on list
list.setSelectedIndex(0); // set selected index to 0
}
};
d.addComponent(list); // add list in dialog
d.show(); // show dialog
}
});
This code shows my list in dialog and starts ticker initially. If it doesn't help, post your code, i will try to see it.

Resources