I'm wanting to bind more than 2 properties to my list is this even possible check my code below
<ListView x:Name="APRListView"
Grid.Row="4"
Grid.RowSpan="5"
Grid.Column="0"
Grid.ColumnSpan="4"
Margin="10,-20,-50,-300">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell
Text="{Binding ProductName}"
Detail="{Binding Monthly}"
/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Is there another approach to this?
I would also like to add text to the detail also ie on Detail="{Binding Monthly}" I'd like it to return on the frontend - Monthly: {Monthly}
use a ViewCell to compose your own layout, and use a Label with FormattedText to include multiple sources of text in one Label
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Text="{Binding ProductName}" />
<Label Text="{Binding Monthly}" />
<Label.FormattedText>
<FormattedString>
<Span Text="Monthly: " />
<Span Text="{Binding Monthly}" />
</FormattedString>
</Label.FormattedText>
</StackLayout>
</ViewCell>
</DataTemplate>
According to Jason's code, you can also try to use StringFormat binding in label, please take a look:
<ListView HasUnevenRows="True" ItemsSource="{Binding products}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
<Label Margin="10" Text="{Binding ProductName}" />
<Label Text="{Binding Monthly, StringFormat='Monthly: {0:N}'}" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
The Screenshot is :
Please check my code it will help you to find multiple bindings to textcell :
XAML Code
<ListView HasUnevenRows="True" ItemsSource="{Binding DemoItems}" SeparatorVisibility="None">
<ListView.ItemTemplate>
<DataTemplate>
<TextCell Text="{Binding name}" TextColor="Red" Detail="{Binding details}" DetailColor="Green">
</TextCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Binding ViewModel
this.BindingContext = new TestPageViewModel();
ViewModel Code:
public class TestPageViewModel : PlusDoctor.ViewModels.BaseViewModel
{
private ObservableCollection<DemoDTO> demoItems;
public ObservableCollection<DemoDTO> DemoItems
{
get { return demoItems; }
set
{
demoItems = value;
OnPropertyChanged();
}
}
public TestPageViewModel()
{
DemoItems = new ObservableCollection<DemoDTO>() {
new DemoDTO(){ name="abc", details="ABC details" }, new DemoDTO(){ name="xyz", details="XYZ details" } };
}
}
Data Model
public class DemoDTO
{
public string name { get; set; }
public string details { get; set; }
}
Output :
Hope it will work for you
Thanks
Related
I have created the following ListView to display data
<dataControls:RadListView x:Name="ItemsListView"
ItemsSource="{Binding StudyResults,Mode=TwoWay}"
MinimumHeightRequest="70"
HeightRequest="{Binding Height}"
SelectedItem="{Binding SelectedItem,Mode=TwoWay}">
<dataControls:RadListView.ItemTemplate>
<DataTemplate>
<listView:ListViewTemplateCell>
<listView:ListViewTemplateCell.View>
<Grid Padding="2,2,2,5" HorizontalOptions="FillAndExpand">
<StackLayout Padding="5,1,1,5" Grid.Column="0">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<maxline:XfMaxLinesLabel MaxLines="2" Text="{Binding BriefTitle, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}" TextColor="Black"/>
</Grid>
<StackLayout Padding="0,0,0,0" HorizontalOptions="Fill">
<BoxView Margin="0"
BackgroundColor="Gray"
HeightRequest=".25" />
<Label Text="{Binding ClosestFacility.Name, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}"/>
<BoxView Margin="0"
BackgroundColor="Gray"
HeightRequest=".25" />
</StackLayout>
</StackLayout>
</Grid>
</listView:ListViewTemplateCell.View>
</listView:ListViewTemplateCell>
</DataTemplate>
</dataControls:RadListView.ItemTemplate>
</dataControls:RadListView>
I want to reuse this exact same ListView + markup in a other screens/view, just with a different ItemsSource it will be bound to same model. I need to use different item source in different screens.
Is there a better way to create some type of resource so I can reuse this?
As lvan's opinion, you can set DataTemplate in ContentPage.Resource or ResourceDictionary, Some code like this:
<ContentPage.Resources>
<DataTemplate x:Key="Radtemplate">
<listView:ListViewTemplateCell>
<listView:ListViewTemplateCell.View>
<Grid Padding="2,2,2,5" HorizontalOptions="FillAndExpand">
<StackLayout Padding="5,1,1,5" Grid.Column="0">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<maxline:XfMaxLinesLabel MaxLines="2" Text="{Binding BriefTitle, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}" TextColor="Black"/>
</Grid>
<StackLayout Padding="0,0,0,0" HorizontalOptions="Fill">
<BoxView Margin="0"
BackgroundColor="Gray"
HeightRequest=".25" />
<Label Text="{Binding ClosestFacility.Name, Mode=TwoWay}" Style="{StaticResource ListViewLabelStyle}"/>
<BoxView Margin="0"
BackgroundColor="Gray"
HeightRequest=".25" />
</StackLayout>
</StackLayout>
</Grid>
</listView:ListViewTemplateCell.View>
</listView:ListViewTemplateCell>
</DataTemplate>
</ContentPage.Resources>
<StackLayout>
<!-- Place new controls here -->
<dataControls:RadListView x:Name="ItemsListView" ItemTemplate="{StaticResource Radtemplate}"
ItemsSource="{Binding StudyResults,Mode=TwoWay}"
MinimumHeightRequest="70"
HeightRequest="{Binding Height}"
SelectedItem="{Binding SelectedItem,Mode=TwoWay}">
</dataControls:RadListView>
</StackLayout>
About DateTemplate detailed info, you can take a look the following article:
https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/templates/data-templates/creating
Update:
Because RadListView is the third party control, I can not install it, so I use ListView as an example, it is the same, you can take a look how to use TapGestureRecognizer.
Please give the Page an x:name=listviewpage firstly, then
<ContentPage
x:Class="demo3.listviewsample.Page2"
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="listviewpage"
mc:Ignorable="d">
<ContentPage.Resources>
<DataTemplate x:Key="datatemplate1">
<ViewCell>
<StackLayout Margin="5" VerticalOptions="FillAndExpand">
<BoxView BackgroundColor="AliceBlue" HeightRequest="30" />
<Label Text="{Binding username}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding BindingContext.command, Source={x:Reference listviewpage}}" CommandParameter="{Binding Email}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ContentPage.Resources>
<ContentPage.Content>
<StackLayout>
<ListView
HasUnevenRows="True"
ItemTemplate="{StaticResource datatemplate1}"
ItemsSource="{Binding models}" />
</StackLayout>
</ContentPage.Content>
Or you can give ViewCell an x:Name viewcell1 firstly, then:
<ContentPage.Resources>
<DataTemplate x:Key="datatemplate1">
<ViewCell x:Name="viewcell">
<StackLayout Margin="5" VerticalOptions="FillAndExpand">
<BoxView BackgroundColor="AliceBlue" HeightRequest="30" />
<Label Text="{Binding username}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Parent.BindingContext.command, Source={x:Reference viewcell}}" CommandParameter="{Binding Email}" />
</Label.GestureRecognizers>
</Label>
</StackLayout>
</ViewCell>
</DataTemplate>
</ContentPage.Resources>
public partial class Page2 : ContentPage
{
public ObservableCollection<model3> models { get; set; }
public RelayCommand1 command { get; set; }
public Page2()
{
InitializeComponent();
models = new ObservableCollection<model3>()
{
new model3(){username="cherry",Email="cherry#outlook.com"},
new model3(){username="barry",Email="barry#outlook.com"}
};
command = new RelayCommand1(obj => method1((string)obj));
this.BindingContext = this;
}
private void method1(string str)
{
Console.WriteLine("the email is {0}",str);
}
}
public class model3
{
public string username { get; set; }
public string Email { get; set; }
}
Here is the Command that inherit ICommand:
public class RelayCommand1 : ICommand
{
private readonly Predicate<object> _canExecute;
private readonly Action<object> _execute;
public RelayCommand1(Action<object> execute)
: this(execute, null)
{
}
public RelayCommand1(Action<object> execute, Predicate<object> canExecute)
{
_execute = execute;
_canExecute = canExecute;
}
public bool CanExecute(object parameter)
{
return _canExecute == null ? true : _canExecute(parameter);
}
public event EventHandler CanExecuteChanged;
public void Execute(object parameter)
{
_execute(parameter);
}
}
When I tap label, it works fine.
You can set DataTemplate as resource, that would work.
I have a ListView displaying multiple cases, and I would like to display its page details when I click on the the Reference from the list. I only get a blank page.
I have tried EventHandler from my XAML and did not work.
<ListView ItemsSource="{Binding GetCases}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Margin="20,0,20,0">
<Label Text="Case Reference:" FontSize="14" TextColor="Green"/>
<Label FontSize="12" TextColor="Blue" FontAttributes="Bold">
<Label.FormattedText>
<FormattedString>
<Span Text="{Binding Reference}" TextColor="Blue" TextDecorations="Underline"> // I can get the list of References here, but can go to their details
<Span.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped" NumberOfTapsRequired="1" />
<TapGestureRecognizer Command="{Binding Path=BindingContext.GoToPageDetails, Source={x:Reference Page}}" /> //This approach takes me to the Page Details, but it is blank
</Span.GestureRecognizers>
</Span>
</FormattedString>
</Label.FormattedText>
</Label>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
VIEWMODEL
public CasesViewModel(INavigation navigation)
{
IGetDataFromServer cases = new GetDataFromServer();
Navigation = navigation;
GoToPageDetails = new Command(async () => await PageDetails());
GetCases = cases.GetCases(); // This code retrieves my data from server - it Works fine
}
public Command GoToPageDetails { get; set; }
public async Task PageDetails()
{
await Navigation.PushAsync(new CaseDetails());
}
CASE DETAILS XAML
<ListView ItemsSource="{Binding GetCases}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Margin="20,0,20,0">
<Label Text="PERSONAL DETAILS" FontSize="Large" TextColor="Black" Margin="0,0,0,20" />
<Label Text="Status:" FontSize="14" TextColor="Green"/>
<Label Text="{Binding status}"
FontSize="12" TextColor="Black" />
</StackLayout>
</ViewCell.View>
</ViewCell>
</ DataTemplate>
</ ListView.ItemTemplate>
</ ListView>
CASE DETAILS VIEWMODEL
public CaseDetailsViewModel(INavigation navigation)
{
IGetDataFromServer cases = new GetDataFromServer();
Navigation = navigation;
GetCases = cases.GetCases().FirstOrDefault();
}
public CasesFull GetCases { get; set; }
I can navigate to Case Details page, but it is blank. Maybe I am not passing the reference to the page, or maybe it is something else.
Thanks for your help.
I finally solved the problem.
The issue was in my Case Details View Model, as I had to add the Model in all properties of the Cases Details View model (see below).
<ListView ItemsSource="{Binding GetCases}" HasUnevenRows="True">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout Margin="20,0,20,0">
<Label Text="PERSONAL DETAILS" FontSize="Large" TextColor="Black" Margin="0,0,0,20" />
<Label Text="Status:" FontSize="14" TextColor="Green"/>
<Label Text="{Binding Case.status}"
FontSize="12" TextColor="Black" />
</StackLayout>
</ViewCell.View>
</ViewCell>
</ DataTemplate>
</ ListView.ItemTemplate>
Where Case is my Model.
If anyone wants to display details of an object, this code can be your solution.
Thanks Umar3x for your help.
I am using radio button with listview and on listview item click I want to make radio button checked/selected but unfortunately not able to select the radio button.
<StackLayout VerticalOptions="CenterAndExpand" HeightRequest="200" HorizontalOptions="CenterAndExpand" >
<ListView RowHeight="45" IsVisible="true" ItemsSource="{Binding Items}" BackgroundColor="#5679d1"
SelectedItem="{Binding objItemSelected, Mode=TwoWay}"
HasUnevenRows="true" SeparatorVisibility="Default" SeparatorColor="White">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid>
<Label Text="{Binding Questions}" TextColor="Black" Grid.Column="0"
Grid.Row="0" Grid.ColumnSpan="2" HorizontalOptions="Center">
</Label>
<controls:CustomRadioButton HeightRequest="15" HorizontalOptions="End" Checked="{Binding Radiobtn}" IsVisible="true" Grid.Row="0" Grid.Column="3"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
You haven't posted the code for objItemSelected, so you may need to mix it with my answer, but to achieve what you want you should have this:
public object objItemSelected
{
get => null;
set
{
if (value == null)
return;
value.Radiobtn = true;
onPropertyChanged(nameof(objItemSelected));
}
}
According to your description, I guess that you want to have two event, one is ListView Itemselected, another is RadioButton check event in Listview. I do one sample about this, but I add Button in listview, replace RadioButton, you can take a look:
<StackLayout>
<ListView ItemsSource="{Binding models}" RowHeight="40" ItemSelected="ListView_ItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout HorizontalOptions="StartAndExpand" Orientation="Horizontal">
<Label
x:Name="label1"
Text="{Binding Name}"
TextColor="Black" />
<Button x:Name="btn1" Text="{Binding Description}" Clicked="OnButtonClick" />
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackLayout>
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
testmodel model = (testmodel)e.SelectedItem;
//Console.WriteLine(model.Name);
DisplayAlert("Alert", model.Name, "OK");
}
private void OnButtonClick(object sender, EventArgs e)
{
Button btn = (Button)sender;
StackLayout listviewiten = (StackLayout)btn.Parent;
Label label = (Label)listviewiten.Children[0];
DisplayAlert("Alert", label.Text, "OK");
//Console.WriteLine(label.Text);
}
I need to access the OnOff property in a Switch within the ListView.GroupHeaderTemplate this property is in the collection used by ListView.ItemTemplate, I have tried in many ways without success, has anyone ever had this problem?
>
<ListView
ItemsSource="{Binding ItemsGrouped}"
GroupShortNameBinding="{Binding Key}"
IsGroupingEnabled="true"
GroupDisplayBinding="{Binding Key}"
x:Name="ListViewAllDevices">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell.View>
<StackLayout>
<Label Text="{Binding Title}"/>
<Label Text="{Binding Description}"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<Label Text="{Binding Key}" />
<Switch IsToggled="{Binding OnOff, Source={x:Reference Name=ListViewAllDevices}}"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
I think you may to change the viewModel .Each groupHeaderTemplate can bind one value. My code as below:
Model
public class Person
{
public string FullName
{
get;
set;
}
public string Address
{
get;
set;
}
}
public class Group : ObservableCollection<Person>
{
public Group(bool key)
{
Key = key;
}
public bool Key
{
get;
private set;
}
}
ItemSource
listView.ItemsSource = new[] {
new Group (true) {
new Person { FullName = "Ass" ,Address = "cole house" }
},
new Group (false) {
new Person { FullName = "Caprice Nave" }
},
new Group (false) {
new Person { FullName = "James Smith", Address = "404 Nowhere Street"},
new Person { FullName = "John Doe", Address = "404 Nowhere Ave" }
}
};
XMAL
<ListView x:Name="listView" IsGroupingEnabled="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<Label Text="{Binding FullName}"/>
<Label Text="{Binding Address}"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<StackLayout>
<Switch IsToggled="{Binding Key}"/>
</StackLayout>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
</ListView>
PS: Once you setListView.GroupHeaderTemplate ,ListView.GroupDisplayBinding will set to null automatically, so you don't need to set ListView.GroupDisplayBinding , but don't forget IsGroupingEnabled="true"
I have a Xamarin Forms application using Android and UWP. Everything works fine under Android but under UWP I have a problem when I want to modify some values displayed on the screen.
Here is my (simplified) ViewModel (using Fody.PropertyChanged) :
public class SalesViewModel : BaseAppViewModel
{
public ObservableCollection<SaleModel> Sales { get; set; }
= new ObservableCollection<SaleModel>();
[DoNotNotify]
public ICommand AddQuantityCommand => new Command<SaleModel>(item =>
{
item.Quantity += 1;
});
}
The BaseAppViewModel implement the INotifyPropertyChanged interface for Fody.PropertyChanged
The (simplified) SaleModel class:
public class SaleModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public double Quantity { get; set; }
}
And the (part of the) XAML which display the list of SaleModel's
<ListView x:Name="ListView" ItemsSource="{Binding Sales, Mode=TwoWay}" SelectedItem="{Binding SelectedSale, Mode=TwoWay}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="arrow.png">
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Path=BindingContext.AddQuantityCommand, Source={x:Reference Name=SalesPage}}" CommandParameter="{Binding .}" />
</Image.GestureRecognizers>
</Image>
<Label Grid.Column="1" Text="{Binding Quantity, Mode=OneWay}"
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
When clicking on the Image, the quantity is incremented but the value disappear from the screen under UWP.
I have tested your code and reproduced your issue. And I written the following ViewCell replace yours. Please try to modify your ViewCell.
<ViewCell>
<StackLayout BackgroundColor="#eee"
Orientation="Vertical">
<StackLayout Orientation="Horizontal">
<Image Source="time.jpg" HeightRequest="50" WidthRequest="50" >
<Image.GestureRecognizers>
<TapGestureRecognizer Command="{Binding AddQuantityCommand} " CommandParameter="{Binding .}"/>
</Image.GestureRecognizers>
</Image>
<Label Text="{Binding Quantity}"
TextColor="#f35e20" />
<Label Text="{Binding Quantity}"
HorizontalOptions="EndAndExpand"
TextColor="#503026" />
</StackLayout>
</StackLayout>
</ViewCell>
I have upload code sample to github. Please refer to.