How tell command (on page) which control was pressed? - xamarin.forms

i have a big knot in my brain.
The current Situation is the following:
in my xamarin Forems App i have on some Pages a UserControl (House) witch Contains multiple Controls (Floor) and this has also multiple Controls (Rooms) in it.
This is all working perfectly and i have coll control for each room over a HouseControler Class
On my RoomControl i have:
<Grid.GestureRecognizers>
<TapGestureRecognizer Command="{Binding Source={x:Reference Root}, Path=RoomTappedCommand}" />
</Grid.GestureRecognizers>
this is totally perfekt. and i got my command perfectly fired in the Breakpoint.
But what i want to acheve is to open nut just an alert but a custom Popup with a Navigation from the current Page with the Informations of the Tapped Room.
So in need do pass somehow the informations from the RoomControl up to the Page. But i dont know how.
i would love to read some tipps.
Thank you Guys =)

you can always get a reference to the currently active page using App.Current.MainPage. To display an alert, for example
App.Current.MainPage.DisplayAlert(...);

Related

CollectionView template calls converter incorrectly

Xamarin.Forms 5.0.0.2012, Visual Studio 2019 for Mac 8.10.16
I am encountering a problem (on both iOS and Android, on both emulators and physical devices) trying to call a Converter in the XAML describing a new screen in our app. This is the markup:
<ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:internal="clr-namespace:Views.Shared"
x:Class="Views.EditPage">
<ContentPage.Resources>
<internal:PictureNameToImageSourceConverter x:Key="PictureNameToImageSourceConverter" />
</ContentPage.Resources>
...
<CollectionView
x:Name="picturesView"
ItemsLayout="HorizontalList"
HeightRequest="90">
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="False" Padding="5">
<Image
HeightRequest="80"
Source="{Binding Path=., Converter={StaticResource PictureNameToImageSourceConverter}}" />
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
The CollectionView.ItemsSource value is set in code to a List<string> instance. When the List has no items, the screen displays correctly. When it does have items the app crashes as the screen appears. If I launch the app attached to the VS debugger, the screen freezes before the crash, and I never get any information.
This converter is well tested and is used several other places in the app with no problem. When I replace the Image with <Label Text="{Binding Path=.}"/> the text items are displayed as expected, so it doesn't look like a binding or Path syntax error.
Is there something I'm not seeing or not aware of in the markup that's causing this? Or can anyone suggest further debugging I haven't thought of?
UPDATE
A breakpoint on the very first line of the converter was never reached.
EDIT in response to comments:
From the EditPage codebehind:
public partial class EditPage : ContentPage
{
internal List<string> PictureNames;
...
protected override void OnAppearing( )
{
base.OnAppearing();
picturesView.ItemsSource = PictureNames;
}
The PictureNames property is actually set by a different Page to which one navigates from the EditPage:
private void saveSelection_Click(object sender, System.EventArgs args)
{
creator.PictureNames = new List<string>();
foreach (SelectableItem<Picture> item in pictureItems)
{
if (item.IsSelected)
{
creator.PictureNames.Add(item.Item.PictureName);
}
}
Navigation.PopAsync();
}
pictureItems is a List acting as a ListView.ItemsSource on that screen, where pictures are selected or unselected.
UPDATE
After much setting of breakpoints, I've determined that the line picturesView.ItemsSource = PictureNames; is where the crash happens. It seems odd that it only happens when the template is showing an Image, but not a Label, seeing that the converter is never actually called.
UPDATE
The trick of adding the delay did get me to the breakpoint. And what I found is more puzzling than ever: The value parameter being passed to the Convert method of our converter is null. This is the case whether coming back from the picture selection screen, or if I set the bound list in response to a Button rather than in OnAppearing, or if I just set it right in the page constructor.
In addition, when setting a breakpoint on the crashing line, when the display element in the template is a Label everything is as expected, but when the display element is an Image the debugger freezes when trying to look at those values. The problem is apparently something about the fact of calling a converter in this precise situation.
I tested that by adding a different converter to the template:
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="False" Padding="5" HeightRequest="{Binding Path=., Converter={StaticResource PictureNameToHeightConverter}}">
<Label Text="{Binding Path=.}" />
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
Exactly the same result: The value parameter passed to the Convert method is null even though the same bound value in the same template instance is displayed in the Label. If I set a breakpoint on the line assigning the ItemsSource property as before, the debugger freezes.
UPDATE
Finally beginning to suspect that I'm triggering some corner case bug in the framework, I replaced the CollectionView with a CarouselView, and it works correctly:
<CarouselView
x:Name="picturesView"
HeightRequest="90">
<CarouselView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="False" Padding="5">
<Image
HeightRequest="80"
Source="{Binding Path=., Converter={StaticResource PictureNameToImageSourceConverter}}" />
</Frame>
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
I'm adding this as an update to the question rather than as an answer because I still don't actually know the explanation.
I've seen some odd behavior when updating page details in OnAppearing.
Hard to put a finger on exactly when there will be a problem, but the fact that you navigated to another page, so this is OnAppearing during the "back" from that other page is probably a factor.
Try this:
protected override void OnAppearing( )
{
base.OnAppearing();
Device.BeginInvokeOnMainThread( async () => {
// Let the page appear on screen, before setting ItemsSource.
await System.Threading.Tasks.Task.Delay(200);
picturesView.ItemsSource = PictureNames;
});
}
At minimum, this should allow Xamarin to reach the breakpoint in the converter.
——————-
UPDATE
I don’t see any obvious flaw in the code you’ve posted.
You’ve narrowed it down to the line it crashes on.
Yet a breakpoint at start of converter is never reached.
As you say, this is a puzzling combination of facts.
Here is a test to do:
Put breakpoint on the line that crashes.
Copy the values in the list, to a text editor.
Add a button on the current page, that when pressed, fills the list with those same strings, hardcoded as a literal, then sets the ItemSource.
Start over, but this time press the button - Does this work or crash?
That is, remove all the complexity of going to another page, querying values, returning to this page.
I bet this will work. Then you’d have the best situation for debugging: a case that works vs. one that doesn’t.
After that, its “divide and conquer”. Start making the working one more like the broken one, and/or vice versa, until the culprit is identified.
You could try to pass data with the ways below when you do the navigation.
One way is to set the BindingContext to the page which you want to navigate to.
Use the Navigation.PushAsync to navigate the page and reset the BindingContext before the page navigated. You could check the thread i done before for more details. Xamarin Public Class data how to acess it properly
Or you could try to binding to a path property using MVVM.
<Image HeightRequest="80" Source="{Binding path, Converter={StaticResource PictureNameToImageSourceConverter}}" />
Another way is to pass the data to the page which you want to navigate through a Page Constructor.
For more details of this way, check the MS docs. https://learn.microsoft.com/en-us/xamarin/xamarin-forms/app-fundamentals/navigation/hierarchical#passing-data-through-a-page-constructor
While it would be interesting to know why the CollectionView binding isn't behaving as expected in this specific situation, the number of hours spent trying to figure it out has definitely passed the point of diminishing returns, so I just added the images the old-fashioned way. I replaced the CollectionView with a StackLayout:
<StackLayout x:Name="picturesLayout" Orientation="Horizontal" />
And then just added framed images "by hand" in the OnAppearing method:
picturesLayout.Children.Clear();
foreach (string pictureName in PictureNames)
{
picturesLayout.Children.Add(new Frame { Padding = 5, HasShadow = false, Content = new Image { Source = ImageManager.ReadFromDisk(pictureName), HeightRequest = 80 } });
}
(ImageManager handles chores like keeping track of the full path to the appropriate directory.)

Xamarin NetStandard SfListview Item tapped event not firing?

This is just as the title suggests. I've updated my Xamarin Forms project to a 1.6 NetStandard project and now the tapped event on my SfListView isn't working (It just doesn't fire at all).
Does anyone has any suggestions of what could be wrong or have faced anything like this?
EDIT
this is xaml code for SfListView:
<StackLayout HeightRequest="15" Grid.Row="0" HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<xForms:SfListView Orientation="Horizontal" ItemSize="128" ItemsSource="{Binding Categories}" SelectionBackgroundColor="Transparent" IsScrollBarVisible="False">
<xForms:SfListView.ItemTemplate>
<DataTemplate>
<cells:CategoryCell />
</DataTemplate>
</xForms:SfListView.ItemTemplate>
<xForms:SfListView.Behaviors>
<behaviors:SfSelectedItemBehavior Command="{Binding FilterCommand}" />
</xForms:SfListView.Behaviors>
</xForms:SfListView>
</StackLayout>
this structure was working before the update. I use a behavior for item selection.
We have checked with the reported query “SfListView ItemTapped event does not trigger after updating the NetStandard Library” from our side. Unfortunately the reported issue does not occur at our end and the ItemTapped event is fired as expected.
For your reference, we have attached the working sample link below.
Sample link: http://www.syncfusion.com/downloads/support/directtrac/190562/ze/SfListViewSample-670965361
Can you please check in your device whether the issue reproduces in our sample also?
If so, Can you please share the below details?
Whether the reported issue occurs in particular device or all devices? (Can you please share the details of your tested device)
Whether the issue is produced in particular platform?
Whether the issue is produced in particular version of Xamarin.Forms and SfListView? (In our sample, we used XForms (v2.3.4.280) and SfListView(v15.3.0.33))
Also can you please share the share the template in which the SfListView items are loaded?

Numeric UpDown Control for Xamarin Forms

Can any one Please provide Numeric UpDown Control demo with Xamarin Forms
Does this control Available in Xamarin Forms?
thanks
Prashanth
See edit #2.
No there is not a spinner control out-of-the-box. If you do not want to get creative, you could use the Picker control and insert predefined values into it. Picker info here.
Otherwise it would be pretty trivial to create an up and down Button and an Entry or Label. Clicking the up Button increments a number in the Entry or Label. Clicking the down Button decrements a number in the Entry or Label.
*Edit: Just happened to land on Syncfusion's NumericUpDown control which does want you want. You can also get a free community license for the control if you are a lone developer or a group of 5 or fewer people. Community License info here
*Edit #2: Was looking through the Xamarin Views list page here and saw that actually do have a Stepper control now!
You can use Stepper for this:
XAML
<Stepper Value="5"
Minimum="0"
Maximum="10"
Increment="0.1"
HorizontalOptions="LayoutOptions.Center"
VerticalOptions="LayoutOptions.CenterAndExpand"
ValueChanged="OnValueChanged" />
C#
void OnValueChanged(object sender, ValueChangedEventArgs e) {
lbldisp.Text = String.Format("Stepper value is {0:F1}", e.NewValue);
}
https://learn.microsoft.com/en-us/dotnet/api/xamarin.forms.stepper?view=xamarin-forms
maybe this could help. you might want to write a custom render for putting that textBox in between the -/+ buttons but sure if you can use as it is, it works fine.

How to pass data to a viewmodel in Caliburn.Micro

This is probably a very simple question, but at this time I have myself so confused I can't see the answer. Simply put, I have a window that contains a content control. I'm using Caliburn.Micro's conventions to "locate" the view.
The window looks like this:
<Window x:Class="Views.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox/>
<ContentControl x:Name="MyViewModel" Height="Auto" Background="Blue"/>
</Grid>
</Window>
The view itself is successfully found, and the screen displays as I expected. However, MyViewModel needs to make a service call to get information based on what is typed into the text box.
So, what I can't seem to figure out is how one would pass that information from the text box to the view model. I've thought of several options, but they all seem to be too much work which makes me think that I'm missing something simple.
Thanks a lot
Like you said there are a number of things you can do:
You could expose a property on MyViewModel and set it within
MainWindowView.
You could use the EventAgregator, publish an event from the
MainWindowView and subscribe to that event from MyViewModel.
Using MEF you could inject a shared resource between the two
ViewModels, set it in MainWindowViewModel, and be able to access it
from MyViewModel.

How to bind the ItemSource inside the DataGrid to an element outside the DataContext, eg. ViewModel in Silverlight 4

I have a DataGrid with some text columns and a button. I want to bind button to a command on the ViewModel. Since, Columns are inside the context of the ItemSource, i want to change the DataContext for the button to something outside the DataGrid(to a view model, to access the Command) or else Silverlight is not able to find the binding expression for that command on the ItemSource context.
Here is what i am doing but i am unsuccessful in doing so. I am not sure where i am making a mistake
<DataGrid >
...
<Button>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Path=DataContext.CommandToCall, ElementName=DataGridName}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
...
</DataGrid>
I do not get any Binding error on doing this but i cannot invoke the command inside my ViewModel. Please note, it is for silverlight and not WPF.
Thanks
I had this same problem recently. I was using a Telerik RadGridView, and I found a workaround on their support forum. Maybe you can do something similar.
Here's the question, and here's the workaround.

Resources