I just can't get my head around it. My brain melts trying to understand how to bind to a parent's context.
So here I have a (relatively) simple object:
public class BinDefinition
{
public string labelAdresse { get; set; }
public InventoryItem inventoryItem { get; set; }
public List<BinContent> binContents { get; set; }
public List<InventoryProduct> productsinBinContent { get; set; }
public bool showDeleteButton { get; set; }
public bool showTransferButton { get; set; }
public ObservableCollection<ListItem> Items { get; set; }
}
then I have my view model that has two of these bindefinitions.
public class viewModel
{
public binDefinition primaryBin { get; set; }
public binDefinition secondaryBin { get; set; }
}
And finally, the relevant xaml part:
<ListView x:Name="ItemsListView" Grid.Row="1"
ItemsSource="{Binding Items}"
VerticalOptions="FillAndExpand"
HasUnevenRows="true"
RefreshCommand="{Binding LoadItemsCommand}"
IsPullToRefreshEnabled="true"
IsRefreshing="{Binding IsBusy, Mode=OneWay}"
CachingStrategy="RecycleElement"
ItemTapped="ItemsListView_ItemTapped"
Grid.RowSpan="2"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid BackgroundColor="LightBlue">
<Grid.RowDefinitions>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
<RowDefinition Height="20"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="60"></ColumnDefinition>
<ColumnDefinition Width="60"></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Text="{Binding Name}" LineBreakMode="WordWrap" FontAttributes="Bold" FontSize="16" HorizontalOptions="FillAndExpand" />
<Label Grid.Row="1" Text="{Binding EANReference}" LineBreakMode="WordWrap" TextColor="Gray" FontSize="16" HorizontalOptions="FillAndExpand" />
<Label Grid.Row="2" Text="{Binding QuantityDisplay}" LineBreakMode="WordWrap" TextColor="DarkBlue" FontSize="16" HorizontalOptions="FillAndExpand" />
<Button Grid.RowSpan="3" Grid.Column="1" Text="Info" Clicked="btnInfos_Clicked" CommandParameter="{Binding EAN}"/>
<Button Grid.RowSpan="3" Grid.Column="2" Text="Del" Clicked="btnDel_Clicked" CommandParameter="{Binding Id}" IsVisible="{Binding BindingContext.primaryBin.showDeleteButton, Source={x:Reference Inv2PageMainContent}}"/>
<Button Grid.RowSpan="3" Grid.Column="2" Text="Tra" Clicked="btnTransfer_Clicked" CommandParameter="{Binding Id}" IsVisible="{Binding BindingContext.primaryBin.showTransferButton, Source={x:Reference Inv2PageMainContent}}"/>
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I am trying to bind the two final button so that the show up or hide depending on the state of the boolean available in BinDefinition. But at that point, the datacontext of said button is a ListItem (from the Items in the viewModel).
I just don't know how to call back the direct parent to use its property.
edit: apologies, it seems I failed to provide sufficient informations.
the inv2MainpageContent is the name of the page. x:Name = inv2MainPageContent.
The BindingContext of the page is an instance of the viewModel. That viewModel contain two binDefinitions. And in that bin Definition are multiple properties. The three that are important to me are the bool ShowDelete/ShowTransfer and the Collection Items.
The List view in my view has dug into the primaryBin and uses "primaryBin.Items" as its ItemSource. The thing is, I would like to bind the visibility of these objects to the the primaryBin.ShowDelete/ShowTransfer.
Related
In my RecentProductsCV CollectionView, I have two <Label>s named PPriceLabel and PLastPriceLabel:
<CollectionView x:Name="RecentProductsCv" SelectionMode="Single">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Vertical" Span="2"/>
</CollectionView.ItemsLayout>
<CollectionView.EmptyView>
<Label Text="No Product found." HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"/>
</CollectionView.EmptyView>
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Frame CornerRadius="10" HeightRequest="90" WidthRequest="90" Grid.Row="0">
<Image Source="{Binding ProductImage}" Aspect="AspectFit" HeightRequest="90" WidthRequest="90"/>
</Frame>
<Label Text="{Binding ProductName}" TextColor="Black" FontSize="Subtitle" Grid.Row="1"/>
<Label x:Name="PPriceLabel" Text="{Binding ProductPrice, StringFormat='BDT {0}'}" TextColor="#e67e22" FontSize="Caption" Grid.Row="2"/>
<Label x:Name="PLastPriceLabel" Text="{Binding ProductLastPrice, StringFormat='BDT {0}'}" TextDecorations="Strikethrough" FontSize="Micro" Grid.Row="3"/>
<StackLayout Orientation="Horizontal" Grid.Row="4">
<Label Text="{Binding ProductRatings, StringFormat='({0}/5)'}" TextColor="LightGray" FontSize="Caption"/>
<Image Source="ratingStar.png" Aspect="AspectFit" HeightRequest="25" WidthRequest="25"/>
</StackLayout>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
I want to disable PLastPriceLabel if the values of PPriceLabel and PLastPriceLabel are the same.
In your ViewModel, you can add a new property to control whether the PLastPriceLabel is visible or not:
public class myViewModel
{
public bool isAvailable { get; set; }
public string ProductPrice { get; set; }
public string ProductLastPrice { get; set; }
public myViewModel()
{
isAvailable = true;
getData();
}
void getData()
{
if (ProductPrice == ProductLastPrice)
{
isAvailable = false;
}
}
}
In your collectionView, bind the isAvailable to the isVisible property in the Xaml:
<Label x:Name="PLastPriceLabel" IsVisible="{Binding isAvailable}" Text="{Binding ProductLastPrice, StringFormat='BDT {0}'}" TextDecorations="Strikethrough" FontSize="Micro" Grid.Row="3"/>
Then PLastPriceLabel will not be visible when PPriceLabel & PLastPriceLabel value is the same.
Xamarin Community Toolkit has a NotEqualConverter you can use to do this
<Label Text="{Binding ProductLastPrice, StringFormat='BDT {0}'}"
TextDecorations="Strikethrough" FontSize="Micro" Grid.Row="3"
IsVisible="{Binding ProductLastPrice, Converter={StaticResource NotEqualConverter},
ConverterParameter={Binding ProductPrice}}" />
I have been trying to play around Xamarin Forms for a while and then came across to the Listview Grouping. I am not getting done its showing blank list. Please give me help to find where I am going wrong? Thanks in advance
However, My class domain looks like:
public class LineItemTaxDto
{
public int InvoiceLineItemId { get; set; }
public int InvoiceId { get; set; }
public int TaxId { get; set; }
public decimal TaxRate { get; set; }
public decimal TaxAmount { get; set; }
public string TaxName { get; set; }
}
My View Model property look like
public IEnumerable<KeyValuePair<string, ObservableCollection<LineItemTaxDto>>> ReceiptTaxList { get; set; }
My expecting result look like:
My xaml code below
<ListView x:Name="TaxListView"
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
ItemsSource="{Binding Invoice.ReceiptTaxList}"
IsGroupingEnabled="true">
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding Key}" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Label Text="{Binding TaxName}" Grid.Row="0" Grid.Column="0" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" HorizontalTextAlignment="End" Margin="0,5,0,5" />
<Label Grid.Row="0" Grid.Column="1" Text="{Binding TaxAmount, Converter={Helpers:CurrencyAmountConverter}}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" Margin="0,5,0,5" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
EDIT
I am set value in view will appear method
Invoice.ReceiptTaxList = Invoice.InvoiceLineItems.Select(x => { return new KeyValuePair<string, ObservableCollection<LineItemTaxDto>>(x.TaxName, x.LineItemTaxes); });
The value was set properly
I have solved this tricky code not using grouping but now its work as expected
My ViewModel Code
var TaxList = Invoice.InvoiceLineItems.Where(x => x.TaxId > 1).GroupBy(y=>y.TaxId > 1).Select(x =>
{
return new KeyValuePair<LineItemTaxDto, ObservableCollection<LineItemTaxDto>>(new LineItemTaxDto()
{
InvoiceLineItemId = x.First().Id,
InvoiceId = x.First().InvoiceId,
TaxId = x.First().TaxId,
TaxRate = x.First().TaxRate,
TaxAmount = x.Sum(a=>a.TaxAmount),
TaxName = taxlabel + " (" + x.First().TaxName + ")"
}, x.First().LineItemTaxes);
});
var taxes = new ObservableCollection<LineItemTaxDto>();
foreach (var tax in TaxList.GroupBy(tax => tax.Key.TaxId).Select(grp => grp.First()))
{
taxes.Add(tax.Key);
foreach (var subtax in tax.Value.Where(x => x.TaxId > 0))
{
taxes.Add(subtax);
}
}
Invoice.ReceiptTaxList = taxes;
My Xaml Code
<ListView
x:Name="TaxListView"
ItemsSource="{Binding Invoice.ReceiptTaxList}"
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="2"
VerticalOptions="FillAndExpand"
HorizontalOptions="FillAndExpand"
SeparatorVisibility="None"
HasUnevenRows="false"
RowHeight="35"
>
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Grid RowSpacing="0" ColumnSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="150" />
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding TaxName}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" HorizontalTextAlignment="End" Margin="0,5,0,5" />
<Label Grid.Row="0" Grid.Column="1" Text="{Binding TaxAmount, Converter={Helpers:CurrencyAmountConverter}}" FontSize="22" FontFamily="{x:Static resources:Fonts.ArialMTFont}" HorizontalOptions="End" Margin="0,5,0,5" />
</Grid>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
You must use a list of list as items source on listview to get it working. I recommend you to create a class with the properties you want to show at header like this:
public class TaxesObservableCollection<T> : ObservableCollection<T> // Think about to implement INotifyPropertyChanged too, I guess it will be usefull
{
public TaxesObservableCollection(IEnumerable<T> collection, string taxGroupName) : base(collection)
{
TaxGroupName = taxGroupName;
}
private bool taxGroupName;
public bool TaxGroupName
{
get { return taxGroupName; }
set { taxGroupName = value; }
}
}
In your view model:
public IEnumerable<TaxesObservableCollection<LineItemTaxDto>> ReceiptTaxList { get; set; }
Your ListView:
(...) // The rest of it as you did
<ListView.GroupHeaderTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding TaxGroupName}" />
</ViewCell>
</DataTemplate>
</ListView.GroupHeaderTemplate>
(...) // The rest of it as you did
And you fill it this way:
Invoice.ReceiptTaxList = Invoice.InvoiceLineItems.Select(x => { return new TaxesObservableCollection<LineItemTaxDto>(x.LineItemTaxes, x.TaxName); }).ToList();
It should works, please let me know if is that what you wanted.
I have a weird exception where the Compiler tells me that the Specified cast is not valid even though what im doing is very Simple.
I have a ListView binded to a ObservableCollection. And inside my Listview is a ViewCell with a Grid. Xamarin.Forms Version 2.3.2.127
<ListView ItemsSource="{Binding GiftCollection}">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<ViewCell.View>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="20"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0" Text="{Binding GiftName}"/>
<Label Grid.Row="1" Grid.Column="0" Text="{Binding GiftDescription}"/>
<Image Grid.Row="0" Grid.RowSpan="2" Grid.Column="1" Source="{Binding GiftImage}"/>
</Grid>
</ViewCell.View>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
Model:
public class GiftModel {
public string GiftName { get; set; }
public string GiftDescription { get; set; }
public ImageSource GiftImage { get; set; }
}
ViewModel:
public class NextRoundViewModel : BaseViewModel {
public NextRoundViewModel(ApplicationModel applicationModel) {
ApplicationModel = applicationModel;
Initialize();
}
public ApplicationModel ApplicationModel { get; set; }
public ObservableCollection<GiftModel> GiftCollection { get; set; }
public string CurrentRound => "Runde 2";
private void Initialize() {
GiftCollection = new ObservableCollection<GiftModel> {
new GiftModel {
GiftName = "100 Punkte",
GiftDescription = "Test",
GiftImage = ImageSource.FromFile("Star.png"),
},
new GiftModel {
GiftName = "200 Punkte",
GiftDescription = "Test",
GiftImage = ImageSource.FromFile("Star.png"),
},
new GiftModel {
GiftName = "300 Punkte",
GiftDescription = "Test",
GiftImage = ImageSource.FromFile("Star.png"),
},
};
}
}
So ive tried everything but if i use for example a TextCell the Exception is gone.
System.InvalidCastException: Specified cast is not valid. It is just weird because i dont know where to look for the Bug.
I had this problem too, the issue was with the xaml. I had a <StackLayout> inside of my <DataTemplate>, you can remove your <Grid> and that should solve the problem.
Did you know that you could replace the <Grid> with an <ImageCell>:
<ListView.ItemTemplate>
<DataTemplate>
<ImageCell
Text="{Binding GiftName}"
Detail="{Binding GiftDescription}"
ImageSource="{Binding GiftImage}">
</ImageCell>
</DataTemplate>
</ListView.ItemTemplate>
You can place inside with .
Something like this
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<StackLayout>
</StackLayout>
</ViewCell>
</DataTemplate>
Remove the <ViewCell> from the DataTemplate. This should resolve the error. <Grid> will work in <CollectionView>
<ListView.ItemTemplate>
<DataTemplate>
<Grid>
:
:
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
The following code gives the same exception, may help someone:
using ListView or CollectionView but in the ItemTemplate I use BindableLayout.ItemTemplate instead CollectionView.ItemTemplate
<CollectionView Grid.Row="0" ItemsSource="{Binding SummaryInfos}">
<CollectionView.ItemsLayout>
<LinearItemsLayout Orientation="Horizontal" />
</CollectionView.ItemsLayout>
<!-- this code gives the same exception -->
<!-- must use CollectionView instead BindableLayout -->
<BindableLayout.ItemTemplate>
<DataTemplate>
<StackLayout>
<Label Text="{Binding SomeText}"/>
</StackLayout>
</DataTemplate>
</BindableLayout.ItemTemplate>
</CollectionView>
I am using the folloowing class but its not allowing me to display show_times in my xaml its just comming up
popcornpk.datamodel.fetchtiming
public class FetchTiming
{
public string id { get; set; }
public string theater_name { get; set; }
public string address { get; set; }
public List<string> show_times { get; set; }
public string screen_id { get; set; }
public string title { get; set; }
}
public class MovieDetail
{
public MovieDetails movie_details { get; set; }
public List<FetchTiming> fetch_timing { get; set; }
}
My Class call
public async Task<MovieDetail> GetMovieShowtimesAsync()
{
string jsonresult = await WCFRESTServiceCall("GET", "movie_details");
var jarray = JsonConvert.DeserializeObject<MovieDetail>(jsonresult);
return jarray;
}
This is my xamlmethod call I hav eno idea what is going on the data is being returned ok but I just cant seem to dispaly it
private async void listViewShowtimes_Loaded(object sender, RoutedEventArgs e)
{
popcornpk_Dal _dal = new popcornpk_Dal();
MovieDetail _showTimes = await _dal.GetMovieShowtimesAsync();
var listView = (ListView)sender;
listView.ItemsSource = _showTimes.fetch_timing.ToList();
}
Xaml Of DataTemplate
<PivotItem x:Name="pvtShowTimes" Header="showtimes">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ListView x:Name="listViewShowtimes" ItemsSource="{Binding}" Loaded="listViewShowtimes_Loaded">
<DataTemplate>
<StackPanel Height="505">
<TextBlock FontSize="13" x:Name="txtshowtime" Text="{Binding theater_name}" HorizontalAlignment="Left" Margin="19,223,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="212" Foreground="White" Height="29" SelectionChanged="txtTtile_SelectionChanged"/>
<TextBlock FontSize="13" x:Name="txtshow_times" Text="{Binding address}" HorizontalAlignment="Left" Margin="19,223,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="212" Foreground="White" Height="29" SelectionChanged="txtTtile_SelectionChanged"/>
</StackPanel>
</DataTemplate>
</ListView>
</Grid>
</PivotItem>
Below is a screen shot of the app running on the device any help be greatly apreciated.
Ok So i have it at least displaying the thertre name which is good on the show times screen but its still not allowing me to display the show_times field.
<ListView x:Name="listViewShowtimes" ItemsSource="{Binding}" Loaded="listViewShowtimes_Loaded">
<ListView.ItemTemplate>
<DataTemplate>
<Grid Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition />
</Grid.ColumnDefinitions>
<TextBlock FontSize="13" Grid.Row="0" Grid.Column="0" x:Name="txtshowtime" Text="{Binding theater_name}" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Width="212" Foreground="White" Height="29" />
<TextBlock FontSize="13" Grid.Row="1" Grid.Column="0" x:Name="txtshow_times" Text="{Binding show_times}" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Width="212" Foreground="White" Height="29" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
I think what i need to no is how to bind a list of strings through xaml Problem I have i need the show times to appear below the cinema name you see their
You have Text="{Binding show_times}" so In your class FetchTiming,
public List<string> show_times { get; set; }
is a list so if you bind it to a TextBlock, it will simply do ToString(). You have to add inside the template another ListView like:
<TextBlock FontSize="13" Grid.Row="0" Grid.Column="0" x:Name="txtshowtime" Text="{Binding theater_name}" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Width="212" Foreground="White" Height="29" />
<ListView ItemsSource={Binding show_times} />
And will do the trick.
I have a WPF application. It contains OrderBlock object which contains other objects, plesase see a brief view of the class.
public class OrderBlocks
{
private List<Order> _orders;
[XmlElement("tF_Transactions")]
public List<Order> Orders { get { return _orders; } set { _orders = value; OnPropertyChanged("Orders"); } }
}
public class Order : INotifyPropertyChanged
{
[XmlIgnore]
public List<Duplications> DuplicateHolder { get; set; }
}
public class Duplications
{
public string ID { get; set; }
public string Name { get; set; }
public Duplications(string newID, string newName)
{
ID = newID;
Name = newName;
}
}
I have a datagrid that is bound to my object Orders of type List Orders. My datagrid has a row detail so that when a user clicks on a row further details are displayed. I have added a listbox to this row detail. I want this row detail to show a listbox which displays my object DuplicateHolder of type List Duplications.
At the moment the listbox is empty. Please see my attempted XAML code below. Any help would be great as always.
<ListBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Name="lbIdentifier" SelectionMode="Single" DataContext="{Binding OrderBlock}" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=DuplicateHolder.ID}" FontSize="10" HorizontalAlignment="Left" Margin="5,0,0,0"/>
<TextBlock Grid.Column="1" Text="{Binding Path=DuplicateHolder.Name}" FontSize="10" HorizontalAlignment="Left" Margin="5,0,0,0"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Try this
<Listbox ItemSource = {Binding DuplicateHolder}/>
and
<TextBlock Grid.Column="0" Text="{Binding Path=ID}".../>
t seems like you did not set the bindings correctly because the listbox Context should be a list of Duplications and the ItemTemplate should be for one Duplication instance from the list of duplicates. So if the global datacontext is an instance of OrderBlocks the listbox will be bound to the DuplicateHolder of an Order:
<ListBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" Name="lbIdentifier" SelectionMode="Single" DataContext="{Binding Path=DuplicateHolder}" HorizontalContentAlignment="Stretch">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding Path=ID}" FontSize="10" HorizontalAlignment="Left" Margin="5,0,0,0"/>
<TextBlock Grid.Column="1" Text="{Binding Path=Name}" FontSize="10" HorizontalAlignment="Left" Margin="5,0,0,0"/>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>