Bind Command to a template view from viewmodel xamarin prism - xamarin

I use prism on the project. My problem is: i have a View OrdemServicoView and a model OrdemServicoViewModel, OrdemServicoView has a syncfusion list... inside has a DataTemplate with a some propertys pass and i can bind, but when i try use command inside template it doesnt work, the command code is in OrdemServicoViewModel... how can i do that?
OrdemServicoViewModel:
public DelegateCommand<object> ItemSelectedCommand { get; set; }
OrdemServicoView (List):
<syncfusion:SfListView.ItemTemplate>
<DataTemplate>
<templates:OrdemServicoCardView />
</DataTemplate>
</syncfusion:SfListView.ItemTemplate>
In OrdemServicoCardView i try to make a button with ItemSelectedCommand binded

The problem you are having has to do with Binding Context. For instance normally within your View your BindingContext is your ViewModel. When working with a DataTemplate inside of something like a ListView your BindingContext is instead whatever data model you may be passing to that ListView as the ItemsSource. The trick therefore is to be able to reference back to the original ViewModel.
<syncfusion:SfListView.ItemTemplate x:Name="lv">
<DataTemplate>
<Button Text="Some Button"
Command="{Binding BindingContext.MyCommand,Source={x:Reference lv}}" />
</DataTemplate>
</syncfusion:SfListView.ItemTemplate>
How we do it is rather simple, first you need to provide a name on an element that has our ViewModel as it's Binding Context. You can pick anything you like really, I usually just reference the Parent Page but the actual List View will work just fine as well. Next we need to add that named element as the Binding Source. Finally we need to realize our new Binding Context is the Element we added as the Source, so we must prepend our Binding with the BindingContext property to have the proper scope into our ViewModel.

Related

Cancelcommand is not working in sfdatepicker in xamarin forms

I want normal cancel functionality on cancel button click of sfdatepicker footer, I am trying to achieve it by binding command but it is not working. Could any one suggest me any solution for that ?
You can use code like below:
<datePicker:SfDatePicker.FooterView>
<Grid>
<Button Text="Ok"
x:Name="footerViewButton"
Clicked="footerViewButton_Clicked"/>
</Grid>
</datePicker:SfDatePicker.FooterView>
Created in this way, and then create the corresponding method in the ViewModel to achieve logical operations.

How to use a Grid with Bindable Layout (more than one column)

In Xamarin.Forms 3.5 Microsoft introduced us to bindable layouts which can be used to dynamically fill layouts (e.g. StackLayout, Grid, etc.).
To use this in a grid with a single column is pretty straightforward:
<Grid BindableLayout.ItemsSource="{Binding Items}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<Label Text="{Binding MyProperty}"/>
</DataTemplate>
</BindableLayout.ItemTemplate>
</Grid>
Now my question is how this can be used to populate a grid with more than one column due to the fact that DataTemplate only allows one view as content. Sure I could but another Grid in it but this would totally nullify the value of bindable layout in a Grid.
Now my question is how this can be used to populate a grid with more than one column due to the fact that DataTemplate only allows one view as content.
From Bindable Layouts, we can see:
While it's technically possible to attach a bindable layout to any layout class that derives from the Layout class, it's not always practical to do so, particularly for the AbsoluteLayout, Grid, and RelativeLayout classes. For example, consider the scenario of wanting to display a collection of data in a Grid using a bindable layout, where each item in the collection is an object containing multiple properties. Each row in the Grid should display an object from the collection, with each column in the Grid displaying one of the object's properties. Because the DataTemplate for the bindable layout can only contain a single object, it's necessary for that object to be a layout class containing multiple views that each display one of the object's properties in a specific Grid column. While this scenario can be realised with bindable layouts, it results in a parent Grid containing a child Grid for each item in the bound collection, which is a highly inefficient and problematic use of the Grid layout.
If you still want to more column, I suggest you can use StackLayout, it can also meet your requirement.
<StackLayout BindableLayout.ItemsSource="{Binding persons}">
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout Orientation="Horizontal">
<Label Text="{Binding name}" />
<Label Text="{Binding age}" />
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</StackLayout>
Checking this issue, seems that what you are trying to accomplish can't be done with a Bindable Layout using a Grid as a Element.
The documentation isn't as clear as it should, nevertheless.
You can subscribe to BindingContextChanged event and configure then all the items. You have to configure the grid definitions programatically after the event.

ReactiveUI bind to DataTemplate

I have an UWP application with ReactiveUI. I have the following in my DataTemplate:
<MenuFlyoutItem Icon="Edit"
Text="{Binding Resources[EditLabel]}">
Since it is a template, I can't access them in my code behind. So how can I setup the binding here?
I tried the Command but then I can only bind to the item itself and not to the ViewModel of the containing view.
EDIT: I adjusted it that way:
<MenuFlyoutItem Icon="Edit"
Text="{Binding Resources[EditLabel]}"
Command="{Binding DataContext.EditAccountCommand, ElementName=AccountList}"
The Binding does work. I wanted now to add a Converter so I can get the clicked object from the eventargs. But when I add a converter it is executed when the page appears and not when the click is executed. Also I do get the bound command instead of the click arguments.

WP7: Listbox item template doesn't work when edited?

**UPDATED**
Just something quick, hope you guys can help me but i'm having this problem where I open up my wp7 project in blend and i edit the listbox item template and i finish it but. I save everything and go back to VS2010 for Windows phone and hit debug but i look at the phone and i have no items showing up at all. The listbox is just blank.
Code:
<ListBox toolkit:TiltEffect.IsTiltEnabled="True" x:Name="ListBox1" FontSize="42.667" FontFamily="Segoe WP SemiLight" IsSynchronizedWithCurrentItem="False" d:LayoutOverrides="VerticalAlignment">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="sp">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu IsZoomEnabled="False" >
<toolkit:MenuItem Header="Delete" Click="Delete_Click" Name="MenuItem1" />
<toolkit:MenuItem Header="Edit" Click="Edit_Click"/>
<toolkit:MenuItem Header="View" Click="View_Click"/>
<toolkit:MenuItem Header="Share.." Click="Share_Click"/>
</toolkit:ContextMenu>
Quick Brief
The app I'm making is a simple note app which saves notes in to a folder in the isolated storage. It successfully retrieves the items but i just want to make it so that it has the title and a brief description. This is all in one item. I've got to that point and the 2 textblocks have ="{Binding}" this basically just adds the title I'm assuming but i also added the ="{Binding}" to the second textblock so its basically showing the title for both of them. Is there a way to bind it to a specific item? like the second textblock, how can i bind that so that it shows 1st 12 characters inside a text file so basically it just shows the title and a brief description?
Maybe you have designtime-only data?
In case you're using Mvvm Light DataService approach, you define 2 DataServices: one for designtime and another for realtime.
Just random assuming. it would be nice to see some sample.
UPD: you posted wrong code, this one is about ContextMenu. I dont see binding there.
But again, generally talking, there shouldnt be any problems. You just deserialize data into model, say
public class Note
{
public string Name {get; set; }
public string Content; {get; set; }
}
And then you have List (or even ObservableCollection if you want realtime changes like renaming). And then you just bind
<TextBlock Text="{Binding Name}"/>
<TextBlock Text="{Binding Content}"/>
If you want to have a strict limit for Content/Description of 12 characters, you can add either Converter and take only 12 first characters, or introduce new property
class Note
{
***
public string Description { get { return Content.Substring(0, 12); } }
}
UPD2:
Ok, lets start from the very beginning. First, MVVM is recommended pattern for Wp7 applications. I believe, you can google info about it yourself, but here are the most important parts:
Model. Keeps your data (in your case, it is notes names and description).
ViewModel. This is abstract view. You have all logic here, you have all data prepared to be rendered here, but VM have no idea how to render data. In your case, a list of notes would be here.
View. Here is description of your ui. In your case, ListBox would be here.
So, first, make a new project, then use NuGet to install latest Mvvm Light (for example). After installing, you should see folders for viewmodels and models.
Create new class Note, like i described before. It would be your model.
Now, go to viewmodel. In a constructor, add a list of Notes there, call it ListOfNotes. Add manually several items to the list and initialize them (add some random values for Names and Contents fields).
Now, go to view. In the top of the file, there should be something like DataContext = "{Binding MainViewModel, Source={StaticResource ViewModelLocator}}". Inside of the view, add ListBox. It should be something like
<ListBox ItemsSource="{Binding ListOfNotes}" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical">
<TextBlock Text="{Binding Name}" />
<TextBlock Text="{Binding Content}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
So, what would happen now. When you would run your app, your view would be initialized. It would get MainViewModel (because is it set as DataContext, in step 4). In the constructor of MainViewModel, a ListOfNotes would be initialized (see step 3). Then, when page would load ListBox, it would try to find ListOfNotes inside of DataContext (MainViewModel in our case). It should find your list of Notes, and then, every element of the ListBox would be associated with every element of your ListOfNotes. As it is described in DataTemplate, it would try to get Note.Name and Note.Content.

Windows phone Exception on TwoWay DataBinding of TextBox item of a Listbox

I'm having problems on Binding a TextBox to a string ( same problem for StringBuilder).
Here is the xaml:
<ListBox x:Name="MyList" ItemsSource="{Binding ListOfBullets, Mode=TwoWay, Converter=StaticResourcedebugConverter}}">
<ListBox.ItemTemplate>
<DataTemplate>
<local:TaskStepControl Text="{Binding Mode=TwoWay}" AddHnadler="{Binding DelegateForHandlingAddTaskStep, ElementName=uc}"></local:TaskStepControl>
</DataTemplate>
</ListBox.ItemTemplate>
and the Items for the ListBox is:
public ObservableCollection<StringBuilder> ListOfBullets{get{....} set{....}}
I also tried :
public ObservableCollection<string> ListOfBullets{get{....} set{....}}
If I run the app I get an unhalted exception "The parameter is incorrect. "
If I remove Mode=TwoWay then it works but as expected editing the Textboxes don't change the text bound object in ListOfBullets;
What am I doing wrong?
MSDN says that you can't have a two-way binding with an empty property path.
I guess the binding engine can perform a two-way binding only to the specific property, not to the object itself.
My thoughts regarding why it is not allowed:
To keep it simple, you can think that the 'writing' part of the TwoWay binding just sets the provided value on your data source object. So this markup Text={Binding Name, Mode=TwoWay} is similar to that C# code: dataSource.Name = textBox.Text on text updates (of course, the entire binding workflow is much more sophisticated and does other things behind the scenes, but that doesn't matter now).
Your sample tries to do something like listItem = textBox.Text, which doesn't update the real item of your ListOfBullets. Please keep in mind that I have dramatically simplified the way bindings work just to give you an idea of what's happening.
What can you do:
Create a wrapper Model class that will contain your string value and bind to
public ObservableCollection<Model> ListOfBullets {get; set;}
with <local:TaskStepControl Text={Binding Value, Mode=TwoWay} />

Resources