Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public override string ToString()
new GalleryPageFactory(() => new ImageControlPage(), "Image Feature Matrix"),
new GalleryPageFactory(() => new ImageButtonControlPage(), "ImageButton Feature Matrix"),
new GalleryPageFactory(() => new BoxViewControlPage(), "BoxView Feature Matrix"),
new GalleryPageFactory(() => new HybridWebViewControlPage(), "HybridWebView Feature Matrix"),
new GalleryPageFactory(() => new ScrollViewControlPage(), "ScrollView Feature Matrix"),
};

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,222 @@
<?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:Maui.Controls.Sample"
x:Class="Maui.Controls.Sample.HybridWebViewControlPage"
x:DataType="local:HybridWebViewViewModel"
Title="HybridWebViewControlPage">


<Grid Padding="10"
RowSpacing="5">
<!-- Define Grid Rows -->
<Grid.RowDefinitions>
<RowDefinition Height="250"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>

<!-- Row 0: HybridWebView at the top -->
<HybridWebView Grid.Row="0"
x:Name="MyHybridWebView"
DefaultFile="{Binding DefaultFile}"
HybridRoot="{Binding HybridRoot}"
IsVisible="{Binding IsVisible}"
Shadow="{Binding Shadow}"
FlowDirection="{Binding FlowDirection}"
RawMessageReceived="OnRawMessageReceived"
AutomationId="HybridWebViewControl"/>

<!-- Row 1: Title and Status Labels -->
<VerticalStackLayout Grid.Row="1"
Spacing="2">
<Label Text="{Binding Status}"
FontSize="14"
TextColor="DarkGreen"
HorizontalOptions="Start"
AutomationId="StatusLabel"/>

<Grid ColumnSpacing="20">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

<HorizontalStackLayout Grid.Column="0"
Spacing="2">
<Label Text="HybridRoot:"
FontAttributes="Bold"
FontSize="12"
HorizontalOptions="Start"/>
<Label Text="{Binding HybridRoot}"
FontSize="11"
TextColor="Blue"
AutomationId="HybridRootLabel"/>
</HorizontalStackLayout>

<HorizontalStackLayout Grid.Column="1"
Spacing="2">
<Label Text="DefaultFile:"
FontAttributes="Bold"
FontSize="12"
HorizontalOptions="Start"/>
<Label Text="{Binding DefaultFile}"
FontSize="11"
TextColor="Blue"
AutomationId="DefaultFileLabel"/>
</HorizontalStackLayout>
</Grid>
</VerticalStackLayout>

<!-- Row 2: Action Buttons -->
<VerticalStackLayout Grid.Row="2"
Spacing="2">
<Grid RowSpacing="2"
ColumnSpacing="5">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>

<!-- HybridRoot Selection -->
<Label Grid.Row="0"
Grid.ColumnSpan="2"
Text="Select HybridRoot:"
FontSize="12"
FontAttributes="Bold"
HorizontalOptions="Start"/>

<Button Grid.Row="1"
Grid.Column="0"
x:Name="HybridWebView1Button"
Text="HybridWebView1"
Clicked="OnHybridRootButtonClicked"
AutomationId="HybridWebView1Button"/>
<Button Grid.Row="1"
Grid.Column="1"
x:Name="HybridWebView2Button"
Text="HybridWebView2"
Clicked="OnHybridRootButtonClicked"
AutomationId="HybridWebView2Button"/>

<!-- DefaultFile Selection -->
<Label Grid.Row="2"
Grid.ColumnSpan="2"
Text="Select Default File:"
FontSize="12"
FontAttributes="Bold"
HorizontalOptions="Start"/>

<Button Grid.Row="3"
Grid.Column="0"
x:Name="IndexHtmlButton"
Text="index.html"
Clicked="OnDefaultFileButtonClicked"
AutomationId="IndexHtmlButton"/>
<Button Grid.Row="3"
Grid.Column="1"
x:Name="ImageHtmlButton"
Text="image.html"
Clicked="OnDefaultFileButtonClicked"
AutomationId="ImageHtmlButton"/>

<Button Grid.Row="4"
Grid.Column="0"
x:Name="NavigationHtmlButton"
Text="navigation.html"
Clicked="OnDefaultFileButtonClicked"
AutomationId="NavigationHtmlButton"/>
<Button Grid.Row="4"
Grid.Column="1"
x:Name="WebHtmlButton"
Text="web.html"
Clicked="OnDefaultFileButtonClicked"
AutomationId="WebHtmlButton"/>

<!-- Properties Section -->
<Label Grid.Row="5"
Grid.ColumnSpan="2"
Text="Properties:"
FontSize="12"
FontAttributes="Bold"
HorizontalOptions="Start"/>

<HorizontalStackLayout Grid.Row="6"
Grid.Column="0"
Spacing="5">
<CheckBox x:Name="IsVisibleCheckBox"
IsChecked="{Binding IsVisible}"
AutomationId="IsVisibleCheckBox"/>
<Label Text="IsVisible"
VerticalOptions="Center"
FontSize="12"/>
</HorizontalStackLayout>

<HorizontalStackLayout Grid.Row="6"
Grid.Column="1"
Spacing="5">
<CheckBox x:Name="ShadowCheckBox"
IsChecked="{Binding HasShadow}"
AutomationId="ShadowCheckBox"/>
<Label Text="Shadow"
VerticalOptions="Center"
FontSize="12"/>
</HorizontalStackLayout>
<HorizontalStackLayout Grid.Row="7"
Grid.Column="0"
Spacing="5">
<CheckBox x:Name="FlowDirectionCheckBox"
IsChecked="{Binding IsLeftToRight}"
CheckedChanged="OnFlowDirectionCheckBoxChanged"
AutomationId="FlowDirectionCheckBox"/>
<Label Text="FlowDirection: LTR if checked, RTL if unchecked"
VerticalOptions="Center"
FontSize="12"/>
</HorizontalStackLayout>


<!-- Action Buttons -->
<Label Grid.Row="8"
Grid.ColumnSpan="2"
Text="Action Buttons:"
FontSize="12"
FontAttributes="Bold"
HorizontalOptions="Start"/>

<Button Grid.Row="9"
Grid.Column="0"
Text="Evaluate JS"
Clicked="OnEvaluateJavaScriptClicked"
AutomationId="EvaluateJavaScriptButton"/>

<Button Grid.Row="9"
Grid.Column="1"
Text="Send Message to JS"
Clicked="OnSendMessageToJavaScriptClicked"
FontSize="14"
AutomationId="SendMessageButton"/>
<!-- Reset Button -->
<Button Grid.Row="10"
Grid.ColumnSpan="2"
Text="Reset"
Clicked="OnResetButtonClicked"
BackgroundColor="Orange"
FontSize="12"
AutomationId="ResetButton"/>
</Grid>
</VerticalStackLayout>
</Grid>
</ContentPage>
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
using System;
using Microsoft.Maui.Controls;

namespace Maui.Controls.Sample;

public partial class HybridWebViewControlPage : ContentPage
{
private HybridWebViewViewModel _viewModel;

public HybridWebViewControlPage()
{
InitializeComponent();
_viewModel = new HybridWebViewViewModel();
MyHybridWebView.RawMessageReceived += OnRawMessageReceived;
BindingContext = _viewModel;
}

private async void OnEvaluateJavaScriptClicked(object sender, EventArgs e)
{
var result = await MyHybridWebView.EvaluateJavaScriptAsync("document.title");
_viewModel.Status = $"EvaluateJavaScriptAsync Result: {result}";
}

private async void OnHybridRootButtonClicked(object sender, EventArgs e)
{
var button = (Button)sender;
var selectedRoot = button.Text;
_viewModel.HybridRoot = selectedRoot;
MyHybridWebView.HybridRoot = selectedRoot;
try
{
await MyHybridWebView.EvaluateJavaScriptAsync("window.location.reload();");

}
catch (Exception ex)
{
_viewModel.Status = $"HybridRoot changed to: {selectedRoot} (reload failed: {ex.Message})";
}
}

private async void OnDefaultFileButtonClicked(object sender, EventArgs e)
{
var button = (Button)sender;
var selectedFile = button.Text;
_viewModel.DefaultFile = selectedFile;
MyHybridWebView.DefaultFile = selectedFile;

try
{
await MyHybridWebView.EvaluateJavaScriptAsync("window.location.reload();");
}
catch (Exception ex)
{
_viewModel.Status = $"DefaultFile changed to: {selectedFile} (reload failed: {ex.Message})";
}
}

private int _messageCount = 0;
private void OnRawMessageReceived(object sender, HybridWebViewRawMessageReceivedEventArgs e)
{
_messageCount++;
if (string.IsNullOrEmpty(e.Message))
{
_viewModel.Status = $"Message #{_messageCount}: EMPTY";
}
else
{
_viewModel.Status = $"Message: {e.Message}";
}
}

private async void OnSendMessageToJavaScriptClicked(object sender, EventArgs e)
{
try
{
_viewModel.Status = "Sending message to index.html...";
await Task.Delay(500);
var message = $"Hello from C#";
var jsCode = $@"window.receiveMessageFromCSharp('{message}')";
var result = await MyHybridWebView.EvaluateJavaScriptAsync(jsCode);
_viewModel.Status = $"Message sent successfully. Result: {result}";

}
catch (Exception ex)
{
_viewModel.Status = $"Failed to send message: {ex.Message}";
}
}

private void OnFlowDirectionCheckBoxChanged(object sender, CheckedChangedEventArgs e)
{
_viewModel.FlowDirection = e.Value
? FlowDirection.LeftToRight
: FlowDirection.RightToLeft;
}

private async void OnResetButtonClicked(object sender, EventArgs e)
{
_viewModel = new HybridWebViewViewModel();
BindingContext = _viewModel;
MyHybridWebView.HybridRoot = _viewModel.HybridRoot;
MyHybridWebView.DefaultFile = _viewModel.DefaultFile;
await MyHybridWebView.EvaluateJavaScriptAsync("window.location.reload();");

}
}
Loading