- Home
- Forum
- Xamarin.Forms
- Do your controls support MVVM binding?
Do your controls support MVVM binding?
Hi,
I've been struggling with getting your controls to work first time I'm trying them out.
I tried working with them before and the experience was not pleasant.
I tried working with them before and the experience was not pleasant.
For example, MVVM is the recommended data binding pattern for Xamarin forms development, but your examples appear not to use MVVM.
I tried binding to this grid in a ContentView
<sfgrid:SfDataGrid x:Name="dataGrid" ItemsSource="{Binding DataList}" AllowLoadMore="True" LoadMoreCommand="{Binding LoadMoreCommand}" AllowPullToRefresh="True" PullToRefreshCommand="{Binding RefreshCommand}" AllowResizingColumn="True" AutoGenerateColumns="false" AllowSorting="True" AllowMultiSorting="True" AllowEditing="True" SelectionMode="Single" VerticalOverScrollMode="None"> <sfgrid:SfDataGrid.Columns> <sfgrid:GridTextColumn MappingName="Name" HeaderText="Name"></sfgrid:GridTextColumn> <sfgrid:GridPickerColumn MappingName="GlobalId" ItemsSource="{Binding ExpenseGroups}" DisplayMemberPath="Name" ValueMemberPath="Id" HeaderFontAttribute="Bold" HeaderText="Group"> </sfgrid:GridPickerColumn> <sfgrid:GridSwitchColumn MappingName="ActiveFlag" HeaderText="Active?"></sfgrid:GridSwitchColumn> </sfgrid:SfDataGrid.Columns> </sfgrid:SfDataGrid>
This is the ContentView code
public CVGridExpenseCategories() { InitializeComponent(); ThemeManager.ThemeName = Themes.Light; ViewModel = new ExpenseCategoryViewModel(); ViewModel.LoadMoreCommand.Execute(null); BindingContext = ViewModel; } public ExpenseCategoryViewModel ViewModel { get; set; }When it runs, it throws a NullReferenceException. Why is the binding NOT WORKING???And why do all your examples use this inline viewmodel declaration?<sample:SampleView.BindingContext> <local:GettingStartedViewModel x:Name="viewModel" /> </sample:SampleView.BindingContext>Is there something wrong with binding to a viewmodel like this?<sfgrid:SfDataGrid x:Name="dataGrid" ItemsSource="{Binding DataList}" AllowLoadMore="True"Also, why is this not working?<sfgrid:GridPickerColumn MappingName="GlobalId" ItemsSource="{Binding ExpenseGroups}" DisplayMemberPath="Name" ValueMemberPath="Id" HeaderFontAttribute="Bold" HeaderText="Group"> </sfgrid:GridPickerColumn>
How do you reference the BindingContext for the GridPickerColumn from the viewmodel that is not declared inline?
Is this the only way of binding data to the GridPickerColumn?BindingContext="{x:Reference viewModel}"This has been really frustrating. Also, I am not sure your Nuget packages add all the required dependencies to the Platform (Android,iOS) projects. Please look into this.Please I need working answers.Thanks.
SIGN IN To post a reply.
3 Replies
SK
Shivagurunathan Kamalakannan
Syncfusion Team
June 27, 2018 01:46 PM UTC
Hi Ozioma,
Thanks for contacting Syncfusion Support.
- Regarding this question: “For example, MVVM is the recommended data binding pattern for Xamarin forms development, but your examples appear not to use MVVM.”
SfDataGrid can be implemented in MVVM pattern. I have attached a sample in MVVM pattern. Please refer the sample for your reference.
Sample link: http://www.syncfusion.com/downloads/support/directtrac/general/ze/SfDataGridSample-1615750257
Regarding the exception:
- Regarding this question:
We have checked your query and the PickerColumn is working fine in our side. We have prepared a working sample for your reference and you can download the same from the below link. Also refer the below UG link for your reference.
Sample link: http://www.syncfusion.com/downloads/support/directtrac/general/ze/Picker_Sample-551067895
- Regarding this question : “ How do you reference the BindingContext for the GridPickerColumn from the viewmodel that is not declared inline? Is this the only way of binding data to the GridPickerColumn?
BindingContext="{x:Reference viewModel}"”
As of now it is necessary to set BindingContext for the GridPickerColumn. You can set the BindingContext which has been set to the SfDataGrid.
We have logged an issue report regarding this, So that the column considers the BindingContext of the SfDataGrid. The fix will be available in any of our upcoming releases.
Regards,
Shivagurunathan
OZ
Ozioma
October 22, 2018 09:18 PM UTC
Hi,
Thanks guys for making these quality UI controls!
I am back to evaluating them again and I hope my concerns are addressed.
I am back to evaluating them again and I hope my concerns are addressed.
What is WRONG with data binding like this?
ViewModel = new ExpenseCategoryViewModel(); ViewModel.LoadMoreCommand.Execute(null); BindingContext = ViewModel;
The above works with other UI controls I use.
Meanwhile, this is not correct, as per my code
“dataGrid.LoadMoreCommand = new Command(ExecuteLoadMoreCommand);”
The LoadMoreCommand is a valid ICommand reference and works with all other controls when used like this
ViewModel.LoadMoreCommand.Execute(null);Do you controls need the Command reference to be assigned like this?
“dataGrid.LoadMoreCommand = new Command(ExecuteLoadMoreCommand);”
If so please state it clearly, to reduce confusion.
Why do ALL your examples use this pattern??
<ContentPage.BindingContext>
<local:ViewModel x:Name="viewModel"/>
</ContentPage.BindingContext>
And why do you need to create and attach behaviors to a databound control?
Like I asked previously, is something wrong with this style of data binding????
Like I asked previously, is something wrong with this style of data binding????
ViewModel = new ExpenseCategoryViewModel(); ViewModel.LoadMoreCommand.Execute(null); BindingContext = ViewModel;
I mean its simpler and easier to read IMO.
What's the deal with using XAML and behaviours exclusively for databinding?
Thanks
VR
Vigneshkumar Ramasamy
Syncfusion Team
October 24, 2018 03:59 AM UTC
Hi Ozioma,
Regarding your query on LoadMoreCommand,
You can set the SfDataGrid.LoadMoreCommand to any ICommand. We have prepared the sample as per your requirement, in which LoadMoreCommand is binded to the ICommand.
Please find the code snippet of the same below. In the below code, you can observe that SfDataGrid.LoadMoreCommand is binded to the “LoadMore” of type ICommand in the ViewModel.
|
<ContentPage.BindingContext>
<local:ViewModel x:Name="viewModel" />
</ContentPage.BindingContext>
<ContentPage.Content>
<sfgrid:SfDataGrid x:Name="sfGrid"
AutoGenerateColumns="False"
ItemsSource="{Binding OrdersInfo}"
AllowResizingColumn="True"
ColumnSizer="Star"
AllowLoadMore="True"
LoadMoreCommand="{Binding LoadMore}"
IsBusy="{Binding Busy}"
>
<sfgrid:SfDataGrid.Columns>
<sfgrid:GridTextColumn MappingName="OrderID" />
<sfgrid:GridTextColumn MappingName="EmployeeID" />
<sfgrid:GridTextColumn MappingName="CustomerID" />
<sfgrid:GridTextColumn MappingName="ShipCountry" HeaderText="Country"/>
</sfgrid:SfDataGrid.Columns>
</sfgrid:SfDataGrid>
</ContentPage.Content>
//ViewModel.cs
public class ViewModel : NotificationObject
{
internal OrderInfoRepository order;
public ICommand LoadMore { get; set; }
private bool busy;
public bool Busy
{
get
{
return busy;
}
set
{
busy = value;
RaisePropertyChanged("Busy");
}
}
public ViewModel()
{
order = new OrderInfoRepository();
SetRowstoGenerate(50);
LoadMore = new CustomLoadMoreCommand(this);
}
#region ItemsSource
private ObservableCollection<OrderInfo> ordersInfo;
public ObservableCollection<OrderInfo> OrdersInfo
{
get { return ordersInfo; }
set
{
this.ordersInfo = value;
RaiseCollectionChanged("OrdersInfo");
}
}
#endregion
#region ItemSource Generator
public void SetRowstoGenerate(int count)
{
OrdersInfo = order.GetOrderDetails(count);
}
#endregion
}
//CustomLoadMoreCommand.cs
public class CustomLoadMoreCommand : ICommand
{
public event EventHandler CanExecuteChanged;
public ViewModel ViewModel { get; set; }
public CustomLoadMoreCommand(ViewModel viewModel)
{
ViewModel = viewModel;
}
public bool CanExecute(object parameter)
{
return true;
}
public async void Execute(object parameter)
{
// You can write your set of codes that needs to be executed
this.ViewModel.Busy = true;
await Task.Delay(new TimeSpan(0, 0, 5));
for (int i = 0; i < 20; i++)
this.ViewModel.OrdersInfo.Add(this.ViewModel.order.GenerateOrder(this.ViewModel.OrdersInfo.Count + 1));
this.ViewModel.Busy = false;
}
} |
You can download the sample from the below link.
Regarding the query on your below code snippet, You should not call the Command.Execute() as we will be calling the Command.Execute internally, when there is the need for command to be executed. For example we will be calling the LoadMoreCommand.Execute() method internally when the LoadMoreButton as displayed in view and true is returned from the Command.CanExecute() method.
In our example code, we have set the LoadMoreCommand as in the below screenshot, as the framework has provided the Command and we used it in order to reduce the code.
Regarding your query on setting the BindingContext in XAML page:
We have set the BindingContext in XAML page, in order to preserve the MVVM pattern, you can also set it in code behind as per your code example after calling InitializeComponents().
Regarding your query on Behaviors:
We will use the Behaviors to hook the events and define it there, in order to preserve MVVM.
Please let us know if this helpful.
Regards,
Vigneshkumar R
SIGN IN To post a reply.
- 3 Replies
- 3 Participants
-
OZ Ozioma
- Jun 26, 2018 12:29 AM UTC
- Oct 24, 2018 03:59 AM UTC