Unable to create XAML array of views with mvvm:ViewModelLocator - mvvm

I want to make a xamarin forms carousel view containing 2 custom views. I have this code:
<ContentPage x:Class="MainView" xmlns:mvvm="clr-namespace:Prism.Mvvm;assembly=Prism.Forms" xmlns:views="clr-namespace:Views" x:Name="Main">
<CarouselView>
<CarouselView.ItemsSource>
<x:Array Type="{x:Type View}">
<views:View1 mvvm:ViewModelLocator.AutowirePartialView="{x:Reference Main}" />
<views:View2 mvvm:ViewModelLocator.AutowirePartialView="{x:Reference Main}" />
</x:Array>
</CarouselView.ItemsSource>
<CarouselView.ItemTemplate>
<DataTemplate>
<ContentView Content="{Binding .}" />
</DataTemplate>
</CarouselView.ItemTemplate>
</CarouselView>
</ContentPage>
When launching the app, exception is thrown:
Xamarin.Forms.Xaml.XamlParseException: 'Position 80:37. Can not find
the object referenced by Main'
If I just set both views as direct content of the main page, it works fine. What am I doing wrong?
Is there a way to make the collection of views through the MainViewModel?

Related

.NET MAUI TableView collapses when Entry control receives focus

I have a TableView in which I render form controls for data editing.
However, as soon as the Entry control receives focus, the ViewCell seemingly collapses, leaving only the section title and separator borders visible:
<TableView Intent="Data">
<TableRoot>
<TableSection Title="Details">
<ViewCell>
<Grid ColumnDefinitions="0.5*,0.5*">
<Label Text="Manufacturer" />
<Entry Text="{Binding Manufacturer}" Grid.Column="1" />
</Grid>
</ViewCell>
</TableSection>
</TableRoot>
</TableView>
Initial state:
After tapping the Entry element:
I've tried setting a specific height for the Grid and the Entry control, but I get the same result regardless.
Am I missing something obvious here? 🤔
It's a bug in .NET MAUI: https://github.com/dotnet/maui/issues/10322
I ran into this a while ago and reported it. For now, I have created my own table using a Grid.
You can change The TableView HeightRequest property to a large number such as 700.
This is a temporary workaround until the bug is fixed.
<TableView HeightRequest="700">
<TableRoot>
<TableSection>
<!-- Your code goes here -->
</TableSection>
</TableRoot>
</TableView>
But, in most scenarios, you don't know what the Height is so you could set it dynamically in your code behind.
Page constructor:
public MainPage()
{
InitializeComponent();
// if you want your table height to fit half of the page
Table.HeightRequest = this.Height / 2;
// Rest of logic...
}
Xaml:
<TableView x:Name="Table">
<TableRoot>
<TableSection>
<ViewCell>
<Label Text="Example"/>
</ViewCell>
</TableSection>
</TableRoot>
</TableView>

Change ImageButton source based on Theme in xaml

I want to change the Source of an ImageButton in xaml based on the Theme (i.e. Light vs Dark). I get a System.NullReferenceException 'Object reference not set to an instance of an object.' when I use the following:
<ImageButton
Grid.Row="1"
Margin="10"
Command="{Binding CreateCommand}"
Source="{AppThemeBinding Light=add_box_black_48dp.svg, Dark=add_box_light_48dp.svg}"
HorizontalOptions="End"
VerticalOptions="End"/>
If I change the Source to the following everything works
Source="add_box_white_48dp"
Can I use AppThemeBinding to change the ImageButton Source in this way?
<Edited on 6/4/2022 to show xaml for cases that work and those that do not work. Also changed the names of the svg files to reflect light and dark cases>
I am using Visual Studio Community 2022 (64-bit) - Preview
Version 17.3.0 Preview 1.1
This ImageButton xaml throws the exception:
<ImageButton
Margin="10"
Command="{Binding CreateNewAccountCommand}"
Source="{AppThemeBinding Light=add_light.svg, Dark=add_dark.svg}"
HorizontalOptions="End"
VerticalOptions="End"
BackgroundColor="#376489"
CornerRadius="8"
WidthRequest="36"
HeightRequest="36">
</ImageButton>
This ImageButton xaml works and does not throw an exception
<ImageButton
Margin="10"
Command="{Binding CreateNewAccountCommand}"
Source="add_light.svg"
HorizontalOptions="End"
VerticalOptions="End"
BackgroundColor="#abdbe3"
CornerRadius="8"
WidthRequest="36"
HeightRequest="36">
</ImageButton>
This also works and does not throw an exception
<ImageButton
Margin="10"
Command="{Binding CreateNewAccountCommand}"
Source="add_dark.svg"
HorizontalOptions="End"
VerticalOptions="End"
BackgroundColor="#376489"
CornerRadius="8"
WidthRequest="36"
HeightRequest="36">
</ImageButton>
To work cross-platform, refer to .png files. These get built automatically by Maui:
Each image resource needs Property/BuildAction: "MauiImage".
Refer to .png in xaml:
Source="{AppThemeBinding Light=add_box_black_48dp.png, Dark=add_box_light_48dp.png}"
Verified by modifying Maui project's default MainPage, to say:
<Image Source="{AppThemeBinding Light=dotnet_bot.png, Dark=dotnet_bot.png}" ... />
This refers to a Media item dotnet_bot.svg, which (I infer) gets converted by "MauiImage" into a .png resource.
NOTE: Maybe the plan is to be able to leave off the extension. This works on Android, but the image does not show on Windows:
<!-- Doesn't work currently on Windows -->
<Image Source="{AppThemeBinding Light=dotnet_bot, Dark=dotnet_bot}" ... />

How to reference element of navigation property in detail view?

I am trying to get Data from a navigation property to display in my detailview.
Image shows the definition of the entities in sap gateway
The association is a 1:1 association.
If I use the link to the navigation property directly it gives the proper result:
link:
/sap/opu/odata/namespace/PROJECTBUILDER_SRV/PROJEKTSet('00002403')/TechnicalSpecs
result:
<entry xmlns="http://www.w3.org/2005/Atom" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:d="http://schemas.microsoft.com/ado/2007/08/dataservices" xml:base="/sap/opu/odata/namespace/PROJECTBUILDER_SRV/">
<id>/sap/opu/odata/namespace/PROJECTBUILDER_SRV/TECHNICAL_SPECSSet('Test%20Service%202')</id>
<title type="text">TECHNICAL_SPECSSet('Test%20Service%202')</title>
<updated>2021-12-02T13:06:38Z</updated>
<category term="PROJECTBUILDER_SRV.TECHNICAL_SPECS" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme"/>
<link href="TECHNICAL_SPECSSet('Test%20Service%202')" rel="self" title="TECHNICAL_SPECS"/>
<content type="application/xml">
<m:properties>
<d:Equipment>Test Service 2</d:Equipment>
<d:Pspnr>00002403</d:Pspnr>
<d:Turbine>TurbineName</d:Turbine>
<d:NominalPowerE>2,5 MW</d:NominalPowerE>
<d:NominalPowerM>4 MW</d:NominalPowerM>
<d:RotorDiameter>80 M</d:RotorDiameter>
<d:RotorSpeed>5,92/12 RPM</d:RotorSpeed>
<d:GridFrequency>50 HZ</d:GridFrequency>
<d:GeneratorSpeed>379 RPM</d:GeneratorSpeed>
<d:GearboxRatio>50,6</d:GearboxRatio>
<d:NominalTorque>4700 KNM</d:NominalTorque>
<d:MaxTorque>9800 KNM</d:MaxTorque>
</m:properties>
</content>
</entry>
But in ui5 view the fields stay empty (the getEntity-Method isn't called either) - so I must be referencing it in a wrong way:
The view I am in uses a route to PROJEKTSet and inside this view I am trying to say:
<m:Input value="{/TechnicalSpecs>/Equipment}" editable="false" visible="true" id="DetailEquipment"/>
What is the correct way to get the value "Equipment" of Entity TechnicalSpecs, which has an association with PROJEKT?

Xamarin Prism binding same command in multiple views

I've a page view which has TabView and each tabview item is a separate view, containing list.
<TabView>
<TabViewItem HeaderText="Comments">
<TabViewItem.Content>
<local:CommentsListView/>
</TabViewItem.Content>
</TabViewItem>
<TabViewItem HeaderText="Stock">
<TabViewItem.Content>
<local:StockListView/>
</TabViewItem.Content>
</TabViewItem>
<TabViewItem HeaderText="Labour">
<TabViewItem.Content>
<local:LabourListView/>
</TabViewItem.Content>
</TabViewItem>
</TabView>
In each child view I've enabled pulldown and pulldown command in each view is pointing to the same 'RefreshCommand'. I want RefreshCommand to be called once no matter from which view pulldown was performed.
Problem is that if I have say 5 child views then refresh command is called 5 times. Obviously I could bind 5 different commands which calls the same method, but would be nice if I could reuse same command.
Is this possible?
Edit: added sample of view in each tab. They all are the same except pointing to different ItemSource:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:prism="http://prismlibrary.com"
prism:ViewModelLocator.AutowireViewModel="True"
xmlns:custom="clr-namespace:Controls"
xmlns:converter="clr-namespace:Converters"
x:Class="CommentsListView">
<ContentView.Resources>
<ResourceDictionary>
<converter:NegateBooleanConverter x:Key="inverter" />
</ResourceDictionary>
</ContentView.Resources>
<custom:ObjectGridView
x:Name="commentsListView"
ItemsSource="{Binding CommentsList}"
IsPullToRefreshEnabled="{Binding InEditMode, Converter={StaticResource inverter}}"
IsRefreshing="{Binding IsRefreshing, Mode=TwoWay}"
PullToRefreshCommand="{Binding RefreshCommand}"
RowTapCommand="{Binding CommentTapCommand}"
ShowAddButton="True"
AddButtonVisible="{Binding InEditMode}"
AddButtonCommand="{Binding AddButtonCommand}"/>
</ContentView>

Problem Binding Commands to TreeViewItem using MVVMLight

I'm trying to use MVVMLight to bind a TreeViewItem Selected event to a command.
The TreeViewItem's are defined in a HierarchicalDataTemplate so I cannot add Interaction.Triggers (as shown below)
<HierarchicalDataTemplate
x:Key="TreeViewItemTemplate"
ItemsSource="{Binding ChildReportViewModels}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Selected">
<MvvmLight_Command:EventToCommand Command="{Binding LoadReportCommand, Mode=OneWay}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</HierarchicalDataTemplate>
How else can I add the EventTrigger to each TreeViewItem?
Thanks.
I forgot about this question.
For future ref, here's the solution I used...
Instead of trying to bind the EventToCommand to the Selected event of the TreeView,
I bound it to the MouseLeftButtonUpEvent of the TextBlock declared in the HierarchicalDataTemplate for TreeViewItems.
<HierarchicalDataTemplate
x:Key="TreeViewItemTemplate"
ItemsSource="{Binding ChildReportViewModels}"
ItemContainerStyle="{StaticResource TreeViewItemContainerStyle}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonUp">
<gs_cmd:EventToCommand Command="{Binding LoadPublicationCommand, Mode=OneWay}" CommandParameter="{Binding}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
</StackPanel>
</HierarchicalDataTemplate>
I have not much knowledge about MVVMLight and especially about EventTrigger.
But since there is no answer to your qestion yet the codeplex article TreeViewWithViewModel might help. It shows how to bind to SelectedItem and IsExpanded Properties in a wpf-treeview and how these can be used to implement load on demand in the treeview.