I have a WebView inside a HubSection in a Hub control:
<HubSection x:Name="details_section" ...>
<!-- ... -->
<DataTemplate>
<WebView x:Name="webView" VerticalAlignment="Stretch" Margin="0" Height="300" />
</DataTemplate>
</HubSection>
The problem is that, when I make it navigate to an HTML string, it does not render the content.
// I adjusted and simplified the code
WebView wv = elem.FindName("webView") as WebView;
if (wv != null) {
wv.NavigateToString(detailTemplate);
}
Of course I debugged to see that the method actually gets called. Moreover, the LoadCompleted event gets called as well.
The problem is not due to bad HTML code as I tested with plain "<html><body>hello</body></html>".
I solved this issue by using the following extension: https://github.com/timheuer/callisto/blob/master/src/Callisto/Extensions/WebViewExtension.cs
Use:
<ns:MyPage
xmlns:ns="using:mylib"
xmlns:ext="using:WSLibrary.Extensions" ...>
<!-- ... -->
<HubSection x:Name="details_section" ...>
<!-- ... -->
<DataTemplate>
<WebView ext:WebViewExtensions.HtmlSource="{Binding MyHtmlString}" ... />
</DataTemplate>
</HubSection>
<!-- ... -->
</ns:MyPage>
Set HorizontalContentAlignment and VerticalContentAlignment of HubSection to Stretch.
<HubSection x:Name="details_section"
HorizontalContentAlignment="Stretch"
VerticalContentAlignment="Stretch">
Related
I'm new with xamarin and I have a really weird bug which is making me crazy. I have a Collection View inside a Tab Item from xamarin tool kit.
The item template for the collection view consists on elements inside a Grid. Inside the template I have two grids which each one is visible depending on a boolean (IsStaticCheckList) which tells you if you have custom fields or normal fields.
I put my render function on the tap item command from the tab item (in that way I'm able to force the render each time the checklist item is tapped). The problem is that on IOS version the layout is not rendering well when I open the form for the first time but if we repeat the process it does it.
As an additional info:
I'm using the MVVM pattern so I use commands for all actions inside my view model.
The difference between custom and normal fields. In the UI is that you are able add as many normal fields in the list as you want and edit them. But if we are using custom fields you are not able to do those actions as you have a checklist template selected.
This only happens on IOS version, Android version works as expected.
This issue only happens with normal fields (IsStatiChecklist = true) on ios version. I've been debbuging the code but nothing seems to be wrong. At the end the layout is working as expected at second time. But I'm not able to make it work the first time I open the form.
I attached some pictures for reference
Here it is how it looks at first time (the 3 dot menu does not appear and the other fields neither because the content is using more space that it should) So all the elements are moved in some way to the right.
Render issue
Here it is how it looks after I leave the tab and go again to my checklist tab
Render Second time
Here is a screenshot of the other use case which is working correctly in all cases custom fields screenshot
Here I attached my Item Template XAML Code
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="models:CheckListAnswerModel">
<Frame>
<Grid
Margin="-10,-20,0,0"
ColumnDefinitions="Auto,*,25,50,Auto"
ColumnSpacing="3">
<Grid
Grid.Column="0"
Grid.ColumnSpan="2"
Padding="20"
IsVisible="{Binding IsStaticCheckList, Source={RelativeSource AncestorType={x:Type viewModels:AddTaskViewModel}}}">
<Label
Grid.Row="0"
IsEnabled="{Binding Complete, Converter={x:StaticResource InvertedBoolConverter}}"
HorizontalOptions="Start"
Text="{Binding Question}"
VerticalOptions="Center"
IsVisible="{Binding ShowLabel}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding EnableEditionCommand, Source={RelativeSource AncestorType={x:Type viewModels:AddTaskViewModel}}}" CommandParameter="{Binding .}" />
</Label.GestureRecognizers>
<Label.Triggers>
<DataTrigger
Binding="{Binding Complete}"
TargetType="Label"
Value="true">
<Setter Property="TextDecorations" Value="Strikethrough" />
</DataTrigger>
</Label.Triggers>
</Label>
<Entry
Grid.Row="0"
IsEnabled="{Binding Complete, Converter={x:StaticResource InvertedBoolConverter}}"
IsVisible="{Binding ShowEntry}"
Placeholder="Click to add text"
ReturnCommand="{Binding CompleteAddCommand, Source={RelativeSource AncestorType={x:Type viewModels:AddTaskViewModel}}}"
ReturnCommandParameter="{Binding .}"
Text="{Binding Question}"
TextColor="{x:StaticResource PrimaryColor}">
<Entry.Effects>
<effects:BorderlessEntryEffect />
</Entry.Effects>
</Entry>
</Grid>
<ia:Checkbox
Grid.Column="2"
CheckColor="{x:StaticResource WhiteColor}"
FillColor="{x:StaticResource DefaultButtonColor}"
IsChecked="{Binding Complete}"
IsVisible="{Binding Complete}"
OutlineColor="{x:StaticResource DefaultButtonColor}"
Shape="Circle" />
<Image
Grid.Column="3"
IsVisible="{Binding HasTask}"
Scale="0.5"
Source="{x:Static res:Images.CreatedTaskIcon}" />
<ImageButton
Grid.Column="4"
BackgroundColor="Transparent"
Command="{Binding OpenMenuItemCommand, Source={RelativeSource AncestorType={x:Type viewModels:AddTaskViewModel}}}"
CommandParameter="{Binding .}"
Scale="2"
Source="{x:Static res:Images.VerticalMoreIcon}"
VerticalOptions="Center" />
</Grid>
</Frame>
</DataTemplate>
</CollectionView.ItemTemplate>
The Items Source for the collection view is called CheckList which has this definition:
private ObservableCollection<CheckListAnswerModel> _checklist;
public ObservableCollection<CheckListAnswerModel> Checklist
{
get => _checklist;
set
{
_checklist = value;
RaisePropertyChanged(() => Checklist);
}
}
Here is the funtion that tells the view model to add the corresponding items to the Checklist:
private async Task RenderElements()
{
if (_checkListTemplateId > 0)
{
var checklistTemplate = _checkListTemplates.FirstOrDefault(x => x.Id == _checkListTemplateId);
if (checklistTemplate != null)
{
CheckListTemplateText = checklistTemplate.Name;
customFieldAnswer = String.Empty;
_checkListTemplateId = checklistTemplate.Id;
IsStaticCheckList = false;
_checklistAnswerEntities = new List<CheckListAnswerEntity>();
if (Id > 0 && loadAnswers) // taskId > 0
{
_checklistAnswerEntities = await _userTaskManager.GetChecklistAnswerByTaskId(Id);
}
if (_checklistAnswerEntities != null && _checklistAnswerEntities.Count() > 0)
{
await RenderCustomFields(checklistTemplate.ChecklistCustomFields, _checklistAnswerEntities);
}
else
{
await RenderCustomFields(checklistTemplate.ChecklistCustomFields);
}
}
else
{
CheckListTemplateText = AppResources.Label_SelectTemplate;
}
}
else
{
if (HasNormalItems)
{
IsStaticCheckList = true;
Checklist = new ObservableCollection<CheckListAnswerModel>();
foreach (var item in EditTaskParam.TaskListModel.CheckListItems)
{
CheckListAnswerModel model = new CheckListAnswerModel(new CheckListAnswerEntity { TaskId = item.TaskId, ChecklistCustomFieldId = item.Id, Question = item.ItemName });
model.Complete = item.Complete;
model.ShowEntry = false;
model.ShowLabel = true;
model.IsTextEntry = false;
model.IsCustomDropdown = false;
model.IsYesNoEntry = false;
Checklist.Add(model);
}
SetCheckListLabel();
}
else
{
SetCheckListLabel();
}
}
}
In my MainPage.xaml I have a CollectionView in a frame and three image buttons in a frame
I'd like the first button to be visible and when I tap it it makes the other two buttons visible and tap again and make the other two buttons invisible.
Seems pretty straightfoward and I can get it working IF they are all visible at first.
If however the other two buttons start off invisible then the button will not respond.
Aside: I also note that hot reload doesn't seem to work if changes made to the controls(views) inside a frame. I tried without the frames and no difference.
Here's the code:
MainPage.xaml
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Census.ViewModels"
x:Class="Census.MainPage">
<Grid
RowDefinitions="*, 65, 100"
RowSpacing="10">
<Frame Grid.Row="0"
CornerRadius="10"
BorderColor="White"
BackgroundColor="Black"
Margin="0,0,0,0">
<CollectionView ItemsSource="{Binding FriendsOC}"
SelectionMode="Single"
SelectedItem="{Binding SelectedItem}"
SelectionChangedCommand="{Binding SelectionChangedCommand}"
SelectionChangedCommandParameter="{Binding .}" >
<CollectionView.ItemTemplate>
<DataTemplate>
<Grid ColumnDefinitions="*, 200">
<Label Grid.Column="0"
Text="{Binding FName}"
FontSize="20"
TextColor="Yellow" />
<Label Grid.Column="1"
Text="{Binding LName}"
FontSize="20"
TextColor="Yellow" />
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</Frame>
<Frame Grid.Row="1"
CornerRadius="10"
BorderColor="White"
BackgroundColor="Black"
HeightRequest="60"
Margin="0,0,0,0"
Padding="0,2,0,0">
<Grid ColumnDefinitions="*, *, *">
<ImageButton Grid.Column="0"
Source="nullx.svg"
BorderColor="Yellow"
BorderWidth="2"
WidthRequest="45"
HeightRequest="45"
Command="{Binding RevealCommand}"/>
<ImageButton Grid.Column="1"
Source="nullx.svg"
BorderColor="Green"
BorderWidth="2"
WidthRequest="45"
HeightRequest="45"
IsVisible="{Binding ImportVisible}"
Command="{Binding ImportFriendsCommand}"/>
<ImageButton Grid.Column="2"
Source="nullx.svg"
BorderColor="Red"
BorderWidth="2"
WidthRequest="45"
HeightRequest="45"
IsVisible="{Binding DestroyVisible}"
Command="{Binding DestroyCommand}"/>
</Grid>
</Frame>
<Button Grid.Row="2"
Text="Add"
Command="{Binding AddFriendCommand}"
WidthRequest="100"
Margin="25,25,25,25"/>
</Grid>
</ContentPage>
MainPage.xaml.cs
namespace Census;
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
BindingContext = new CensusViewModel();
}
protected override void OnAppearing()
{
base.OnAppearing();
//ImportVisible = false; <--things I tried to no avail
//DestroyVisible = false;
//FriendsList.ItemsSource = await App.Friends.GetFriendsAsync(); //because App.xaml.cs is where th db code is
}
}
and the viewmodel
namespace Census.ViewModels;
public partial class CensusViewModel : ObservableObject
{
[ObservableProperty]
public bool importVisible = true;
[ObservableProperty]
public bool destroyVisible = true;
...
//Reveal Actions
public ICommand RevealCommand => new Command(() =>
{
Console.WriteLine("Reveal");
ImportVisible = !ImportVisible;
DestroyVisible = !DestroyVisible;
});
...
}
This works fine
but if I do
[ObservableProperty]
public bool importVisible = false;
[ObservableProperty]
public bool destroyVisible = false;
It works in terms of hiding the two buttons, but does not respond if I tap the first button, except it does hit the code and change the properties.
Now in my head I am thinking of a question I asked here .net Maui databinding to shell flyout item IsVisible property
I've tried different variation on a theme but haven't been able to figure out what I could do. (Hence why I use the code binding in the codebehind as per the solution.
Just seems so bizarre that it works when the properties start off true and works fine, but not when false.
I've spent a good many hours on this by the way so I do try hard to figure it out myself.
I have a simple webview tag on my xml file, like this:
<WebView src="{{ content }}"/>
I've tried set the background-color to 'transparent' in the css file, also using inline css, but I can't get the webview background set to transparent.
More info about the project:
- nativescript version: 2.2.1
- I have a list of ticket's movements (like incidences about a particular case) on a support system app. This movements usually are html emails (with images, styles and so)... that's because I'm using a webview instead of an htmlview. As you can see in the image, the webview's background is white.
There's my xml snippet:
<!-- Repeat ticket's movs-->
<Repeater items="{{ movs }}">
<Repeater.itemTemplate>
<StackLayout>
<StackLayout class="{{ movClass }}" visibility="{{ id != -1 ? 'visible' : 'collapsed' }}">
<Label class="date" text="{{name + ' #' + dateValue}}"/>
<WebView src="{{ content }}"/>
</StackLayout>
</StackLayout>
</Repeater.itemTemplate>
</Repeater>
In the js file, I fetch the movements from an url and populate the array.
If you need more info, please tell me and I upload it.
Thanks!
BACKGROUND-NOT-TRANSPARENT-WEBVIEW
To make WebView with transparent background color you could use native code. For Android you could use setBackgroundColor method for Android to make background color transparent. For iOS you should use UIColor.clearColor() to remove the webView background color. You could review the below attached sample code. In regard to that you should also add tns-platform-declarations plugin in your project, that would allow you to use some native methods in your typescript code.
main-page.xml
<Page xmlns="http://schemas.nativescript.org/tns.xsd" navigatingTo="navigatingTo">
<GridLayout rows="* 70 70" columns="*" backgroundColor="green" >
<WebView row="0" loaded="wvloaded" id="wv" class="webviewStyle" src="
<html style='background-color: transparent;'>
<body style='background-color: transparent;'>
<h1>My First Heading</h1>
<p>My first paragraph.</p>
</body>
</html>" />
<Label row="1" text="{{email}}" textWrap="true" />
<Label row="2" text="{{password}}" textWrap="true" />
</GridLayout>
</Page>
main-page.ts
import { EventData } from "tns-core-modules/data/observable";
import { Page } from "tns-core-modules/ui/page";
import { HelloWorldModel } from "./main-view-model";
import {WebView} from "tns-core-modules/ui/web-view";
import {isIOS, isAndroid} from "tns-core-modules/platform"
var Observable = require("data/observable").Observable;
var user = new Observable({
email: "user#domain.com",
password: "password"
});
// Event handler for Page "navigatingTo" event attached in main-page.xml
export function navigatingTo(args: EventData) {
// Get the event sender
var page = <Page>args.object;
page.bindingContext = user;
}
export function wvloaded(args:EventData){
var newwv:WebView =<WebView> args.object;
if(isAndroid){
newwv.android.setBackgroundColor(0x00000000);//android.graphics.Color.TRANSPARENT);//
newwv.android.setLayerType(android.view.View.LAYER_TYPE_SOFTWARE, null);
}
if(isIOS){
newwv.ios.backgroundColor = UIColor.clearColor;
newwv.ios.opaque=false;
}
}
I have written a listbox to display the "Engine Size" of a set of data from an XML sheet, the item binding seems to work, and the listbox works prefectly for the first two options however the rest are completly unclickable.
I have tried breaks in the code and it is showing that clicking on one of the not working values doesnt even trigger the "ListPicker_ChangedSelection" program i have.
The code I have is below.
private void Choose_Engine_Size_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
String carenginesize=((enginesize)Choose_Engine_Size.SelectedItem).Esize.ToString();
List<enginesize> enginesize =GetCarData();
foreach (enginesize c in enginesize)
{
if(c.Esize==carenginesize)
{
ConsumptionBox.Text=c.Consumption;
EmmissionsBox.Text=c.Emissions;
}
}
From this is then goes to make some caluclation with the populated values from this.
My Listpicker code is as follows:
<toolkit:ListPicker HorizontalAlignment="Left" Margin="287,22,0,0" x:Name="Choose_Engine_Size" VerticalAlignment="Top" Width="72" SelectionChanged="Choose_Engine_Size_SelectionChanged" Height="Auto" Opacity="1">
<toolkit:ListPicker.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Border>
<TextBlock Text="{Binding Esize}" FontSize="20" Width="Auto" HorizontalAlignment="Center"/>
</Border>
</StackPanel>
</DataTemplate>
</toolkit:ListPicker.ItemTemplate>
</toolkit:ListPicker>
I am new to the WP7 platform and I am facing something strange, I have a custom component that has an image. (Part of the custom component below)
<Rectangle x:Name="ImageForeground" Height="240" Width="240" HorizontalAlignment="Center" VerticalAlignment="Center" Fill="{TemplateBinding Foreground}"
DataContext="{TemplateBinding Image}"
OpacityMask="{Binding Converter={StaticResource brushConverter}}" />
Here is the brushConverter
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
BitmapImage image = (BitmapImage)value;
ImageBrush imageBrush = new ImageBrush();
if (image != null)
{
imageBrush.ImageSource = image;
}
return imageBrush;
}
Now i add the custom component to a page with
<rounded:RoundedImageView Image="/Images/image1.png"/>
Here comes the weird part. The component only displays certain png images!! I have 5 all in all, with ALL their Build Action properties set to Content. But the control only loads some and not all. Even stranger is if i put the images in a regular Image component like so
<Image Height="200" HorizontalAlignment="Left" Margin="54,17,0,0" Name="image3" Stretch="Fill" VerticalAlignment="Top" Width="200" Source="/Images/service_reload.png" />
It works!!! WTF!!
Any ideas?!
Solved:
Solved: I attached the brushConverter binding to the Fill property of the Rectangle instead of the OpacityMask property and it worked like a charm
<Rectangle x:Name="ImageForeground" Height="240" Width="240" HorizontalAlignment="Center" VerticalAlignment="Center" DataContext="{TemplateBinding Image}" Fill="{Binding Converter={StaticResource brushConverter}}" />