UWP Prism NavigationService configuration - windows-phone

I've started a UWP project with Prism Library. To navigate between pages I'm using Prism NavigationService. Well everything is ok while I have situation as in bellow image:
Well after login I need to load a window with a split view and later to use NavigationService to change only content of the "red square".
My third page xaml looks like:
<SplitView x:Name="rootSplitView" Style="{StaticResource MenuSplitViewStyle}" Grid.Row="1">
<Frame x:Name="contentFrame"/>
<SplitView.Pane>
<views:MenuViewPage/>
</SplitView.Pane>
</SplitView>
<ToggleButton x:Name="togglePaneButton"
VerticalAlignment="Center"
IsChecked="{Binding IsPaneOpen,
ElementName=rootSplitView,
Mode=TwoWay}"
Style="{StaticResource SplitViewTogglePaneButtonStyle}"
TabIndex="1" />
My app bootstrap is:
public sealed partial class App : PrismUnityApplication
{
protected override Task OnLaunchApplicationAsync(LaunchActivatedEventArgs args)
{
if (args != null && !string.IsNullOrEmpty(args.Arguments))
{
// The app was launched from a Secondary Tile
// Navigate to the item's page
//NavigationService.Navigate("ItemDetail", args.Arguments);
}
else
{
// Navigate to the initial page
NavigationService.Navigate(PageTokens.IntroPage, null);
}
Window.Current.Activate();
return Task.FromResult<object>(null);
}
...
}
My question is how I can create a region in red square and configure navigation service to use the region to navigate between pages.

Related

Custom Frame is not accepting Height Request in MAUI

I am converting my Xamarin Forms Application to .NET MAUI.
I am trying to migrate the Custom renderer from Xamarin to MAUI following this link Using Custom Renderers in .NET MAUI
Here is my Code:
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.UseMauiCompatibility()
.ConfigureMauiHandlers(handlers =>
{
handlers.AddCompatibilityRenderer(typeof(CustomFrame), typeof(CustomShadowFrameRenderer));
});
return builder.Build();
}
CustomFrame:
public class CustomFrame : Frame
{
public CustomFrame()
{
}
}
Below is the Custom Renderer Class
public class CustomShadowFrameRenderer : FrameRenderer
{
public CustomShadowFrameRenderer(Context context) : base(context)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Frame> e)
{
base.OnElementChanged(e);
if (e.NewElement != null && e.OldElement == null)
{
e.NewElement.HeightRequest = 1000;
e.NewElement.VerticalOptions = LayoutOptions.FillAndExpand;
}
}
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiApp1.MainPage" BackgroundColor="Red"
xmlns:local="clr-namespace:MauiApp1.Controls">
<local:CustomFrame BackgroundColor="Blue" HeightRequest="1000" Padding="20">
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
<Label
Text="Hello, World!"
SemanticProperties.HeadingLevel="Level1"
FontSize="32"
HorizontalOptions="Center" />
<Label
Text="Welcome to .NET Multi-platform App UI"
SemanticProperties.HeadingLevel="Level2"
SemanticProperties.Description="Welcome to dot net Multi platform App U I"
FontSize="18"
HorizontalOptions="Center" />
<Button
x:Name="CounterBtn"
Text="Click me"
SemanticProperties.Hint="Counts the number of times you click"
Clicked="OnCounterClicked"
HorizontalOptions="Center" />
</VerticalStackLayout>
</local:CustomFrame>
</ContentPage>
The Frame is not accepting the height Request in MAUI but the same works fine in Xamarin forms.
Below is the image for the same
I have create a sample to test your code and met the same problem. In addition, I even can't click the button in the CustomFrmae. It seems there are some compatibility issues about the FrameRender in the maui.
So I try to change the CustomRender to the CustomHandler. It worked well and you just need to change two place code.
In the CustomShadowFrameRenderer class, make it such as public class CustomShadowFrameRenderer : Microsoft.Maui.Controls.Handlers.Compatibility.FrameRenderer
In the MauiProgram.cs:
var builder = MauiApp.CreateBuilder();
            builder
             .UseMauiApp<App>()
.ConfigureMauiHandlers(handlers =>
{
                  handlers.AddHandler(typeof(CustomFrame), typeof(CustomShadowFrameRenderer));
             })

WebView GestureRecognition not working in Xamarin forms

I have a webview When this webview is tapped I need to make visible of a button the problem Is Gesture recognition is not working
my Xaml
<customRenderer:CustomWebView Uri="{Binding SelectedJournal.Uri}" VerticalOptions="FillAndExpand" HorizontalOptions="FillAndExpand" x:Name="CustomWebView" AbsoluteLayout.LayoutBounds="0,50,1,1" AbsoluteLayout.LayoutFlags="SizeProportional" >
<customRenderer:CustomWebView.GestureRecognizers>
<TapGestureRecognizer Tapped="TapGestureRecognizer_OnTapped2" NumberOfTapsRequired="1" ></TapGestureRecognizer>
</customRenderer:CustomWebView.GestureRecognizers>
</customRenderer:CustomWebView>
<customRenderer:NavigationImageButton ItemTapped="FullScreenOnTapped" Source="full.jpg" AbsoluteLayout.LayoutBounds="0.5,1,-1,-1" AbsoluteLayout.LayoutFlags="PositionProportional" HeightRequest="60" WidthRequest="60" x:Name="FullScreenBtn" IsVisible="False" >
In the code behind i called like this
private void TapGestureRecognizer_OnTapped2(object sender, EventArgs e)
{
FullScreenBtn.IsVisible = true;
}
This should work but this is not working
also my custom rendering web view class
public class CustomWebView : WebView
{
public static readonly BindableProperty UriProperty = BindableProperty.Create<CustomWebView, string>(p => p.Uri, default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
}
How to Achive this
Instead of using the gesture recognizer on your webview, you can use the 'Focused' event of your view to display your button. You can do something like this:
var wb = new WebView
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Source = "https://stackoverflow.com/questions/56320611/webview-gesturerecognition-not-working-in-xamarin-forms",
};
wb.Focused += (s, e) =>
{
//Handle your logic here!
wb.Unfocus();
};
Here, Unfocus() is used if you wish to implement your logic everytime the webview is tapped.
A WebView is used in my application to display formatted text. Tapping the text should open an editor to modify the text. The suggested Focused event works on Android but not iOS (as of iOS 15.0 simulator at least). I found the solution in the comments for https://bugzilla.xamarin.com/42/42596/bug.html#c4. Adding an empty label to the xaml as a transparent overlay of the WebView registers the tap event and enables the gesture recogniser.
<Grid HeightRequest="132">
<WebView Grid.Column="0" Grid.Row="0"
Source="{Binding FormattedDescription, Converter={tr:StringToWebViewSourceConverter}}"
HeightRequest="132"/>
<Label Grid.Column="0" Grid.Row="0" Text=""
HeightRequest="132" HorizontalOptions="Fill">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding EditDescriptionCommand}"/>
</Label.GestureRecognizers>
</Label>
</Grid>

How to change open animation of flyout menu

I have a menu flyout which is opened on ListView Items. The default open animation is quite slow is there a way to change the default animation of flyout menu?
EDIT
I am using following dependency property for showing context menu on list view item it works fine but when context menu is shown it squeezes the the whole view a bit. I do not want to squeeze the page when context menu is opened.
public class OpenMenuFlyoutAction:DependencyObject,IAction
{
public object Execute(object sender, object parameter)
{
if (!Global.IsDisabledShowContextMenuOnListView)
{
FrameworkElement senderElement = sender as FrameworkElement;
FlyoutBase flyoutBase = FlyoutBase.GetAttachedFlyout(senderElement);
flyoutBase.ShowAt(senderElement);
}
return null;
}
}
List Item data template
<DataTemplate x:Key="MemberListItemDataTemplate">
<Grid Width="{Binding ElementName=searchView,Path=ActualWidth}" Background="{Binding ItemBackground}"
Margin="0,0,0,20" Height="auto">
<i:Interaction.Behaviors>
<icore:EventTriggerBehavior EventName="Holding">
<helpers:OpenMenuFlyoutAction />
</icore:EventTriggerBehavior>
</i:Interaction.Behaviors>
<FlyoutBase.AttachedFlyout>
<MenuFlyout>
<MenuFlyoutItem Text="share" RequestedTheme="Dark" Command="{Binding ElementName=pageMyProfile, Path=DataContext.ShareMemberDetails}" CommandParameter="{Binding item99}" />
<MenuFlyoutItem Text="reomve from members" RequestedTheme="Dark" Command="{Binding ElementName=pageMyProfile, Path=DataContext.RemoveMember}" CommandParameter="{Binding item99}" />
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
...
</DataTemplate>
Yeah, you need to create a new Style targeting MenuFlyoutPresenter in your resources
<Style TargetType="MenuFlyoutPresenter">
If you copy it from Program Files (x86)\Windows Phone Kits\8.1\Include\abi\Xaml\Design\generic.xaml you'll notice there are already some storyboards inside for various visual states that you need to change in order to get a different animation.
I wrote about something very similar in my blog post MenuFlyout flip animation on Windows Phone WinRT

Update UserControl Textblock text from mainpage.xaml

I am writing a Windows Phone 8.1 Silverlight App. I made a user control NotificationsIconUserControl. It just contains a BELL/ALARM icon and textblock to display number of unread notifications.
I want to update this textblock text from mainpage.xaml
How to do this?
I tried using usercontrol expose properties but its the opposite thing. Also tried help from this question. how to use dependency property. Please edit the code below:
Usercontrol XAML:
<Grid x:Name="LayoutRoot"
Background="Transparent"
Height="Auto"
Width="Auto">
<Image
Name="Alarm_Icon"
Source="/Images/Status/Notification_Icon_1.png">
</Image>
<Ellipse
Name="Counter_Icon"
Height="45"
Width="45"
Margin="60,14,-6,50"
StrokeThickness="0"
Fill="{StaticResource DefaultTheme_IndianRedColor}">
</Ellipse>
<TextBlock
Name="Counter_Label"
Foreground="{StaticResource DefaultTheme_LightColor}"
FontSize="30"
HorizontalAlignment="Center"
VerticalAlignment="Center"
TextAlignment="Center"
Margin="75,20,8,58"/>
</Grid>
Mainpage XAML part:
xmlns:MyUserControls="clr-namespace:Project.Custom.UserControls">
Mainpage .cs part:
private void ConfigureNotificationsIcon()
{
int NotificationsCounter = 4;
NotificationsIconUserControl NotificationsIconUserControlObject = new NotificationsIconUserControl();
NotificationsIconUserControlObject.Counter_Label.Text = NotificationsCounter.ToString();
}
I checked your code and its working completely....
ANd for the part of adding a Dependency property, write the following in the .cs file of UserControl
public partial class NotificationIconUserControl : UserControl
{
public NotificationIconUserControl()
{
InitializeComponent();
}
public string NotificationLabel
{
get { return (string)GetValue(NotificationLabelProperty); }
set { SetValue(NotificationLabelProperty, value); }
}
// Using a DependencyProperty as the backing store for Spacing. This enables animation, styling, binding, etc...
public static readonly DependencyProperty NotificationLabelProperty =
DependencyProperty.Register("NotificationLabel", typeof(string), typeof(NotificationIconUserControl), new PropertyMetadata("hellllo"));
}
After that you can use TemplateBinding to do your job

Resolve ViewModels in WinPhone 8.1, Prism and Unity

I am developing an Windows Phone 8.1 App with Prism for Windows Store Apps and Unity as IoC container. I got the basics working so far and the convention based resolving of View and ViewModel works so far.
For navigation I want to use a Drawer Layout (with a flyout menu) and display the selected models inside the MainPage (rather than navigating to pages).
So I have a MainViewModel (which gets correctly instantiated and assigned with MainPage, using a custom name convention). And I have a DrawerViewModel. The drawer is inside the MainPage, where also the other ViewModels shall be displayed.
My MainPage.xaml:
<Page
x:Class="StackExchangeReader.Views.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:StackExchangeReader"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:m="using:StackExchangeReader.Models"
xmlns:drawerLayout="using:DrawerLayout"
xmlns:prism="using:Microsoft.Practices.Prism.Mvvm"
xmlns:designViewModels="using:StackExchangeReader.DesignViewModels"
mc:Ignorable="d"
prism:ViewModelLocator.AutoWireViewModel="True"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
d:DataContext="{d:DesignInstance designViewModels:DrawerDesignViewModel, IsDesignTimeCreatable=True}">
<Grid x:Name="RootLayout">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<!-- Title Bar -->
<Grid x:Name="TitleBar" Background="#00ADEF" Grid.Row ="0" Height="60">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Image Margin="5" x:Name="DrawerIcon" Grid.Column="0" Source="/Assets/drawer_icon.png" HorizontalAlignment="Left" Tapped="DrawerIcon_Tapped" />
<TextBlock Grid.Column="1" Text="{Binding Title}" Foreground="White" VerticalAlignment="Center" FontSize="18"/>
</Grid>
<!-- Drawer Layout -->
<drawerLayout:DrawerLayout Grid.Row="1" x:Name="DrawerLayout">
<Grid x:Name="MainFragment" Background="White">
<!-- Main Content goes here -->
</Grid>
<Grid x:Name="ListFragment" Background="#F4F4F4">
<ListView DataContext="{Binding Sites}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" Margin="10" HorizontalAlignment="Left" VerticalAlignment="Center" FontSize="18" Foreground="Black" />
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</drawerLayout:DrawerLayout>
</Grid>
</Page>
The two things here to be notice are:
MainFragment Grid, where the other ViewModels shall be displayed (i.e. after clicking an option in the Drawer Layout menu)
ListFragment Grid, with the options the user can select
Now the actual problem/question:
Since Prism resolves ViewModels and Views by convention, of course...
... it won't resolve the DrawerViewModel.
I can't instantiate it in XAML, cause it doesn't have a parameterless constructor and it has dependencies injected, so it's required that it's resolved via Unity.
Adding a property in MainViewModel could be possible, but then I'd need to inject it. While it would solve this one problem, it doesn't solve the problem that I also need to instantiate the Content (inside MainFragment) too. Also it's a bad idea to make ViewModels independent of each other. After all, MVVM should support loose coupling.
I also tried to define ViewModel dependency on the MainPage class, but Prism/Unity do not seem to be call this constructor (which Unity should do, if they were to be resolved via IoC/DI, because Unity chooses the constructor with the highest number of dependencies when it resolves the class)
I could also inject the IoC container into the MainViewModel, but this makes my ViewModel(s) depend on IoC. And passing IoC into ViewModel is a bad practice anyways.
I also considered using an abstract factory. This would avoid dependency on IoC container, but it feels like it only shifts the problem.
First things first:
What would be the correct and elegant way to assign an instance of DrawerViewModel as ListFragment's DataContext?
Could designing the ListFragment as an UserControl help allow me that the DrawerViewModel is correctly resolved and assigned to it? Anyone (preferably with Enterprise Business Application experience) having the same issues and a solution for this problem?
Just for the record, the two ViewModel classes.
MainViewModel.cs
public class MainViewModel : ViewModel
{
private INavigationService navigation;
private IEventAggregator events;
public MainViewModel(INavigationService navigation, IEventAggregator events)
{
this.navigation = navigation;
this.events = events;
}
public string Title { get; set; } = "Example";
private ViewModel selectedViewModel;
public ViewModel SelectedViewModel
{
get { return selectedViewModel; }
set { SetProperty(ref selectedViewModel, value); }
}
}
DrawerViewModel.cs
public class DrawerViewModel : ViewModel
{
private ISiteService siteService;
private IEventAggregator events;
public DrawerViewModel(ISiteService siteService, IEventAggregator events)
{
this.siteService = siteService;
this.events = events;
sites = new ObservableCollection<Site>();
}
private ObservableCollection<Site> sites;
public ObservableCollection<Site> Sites
{
get { return sites; }
}
}