ApplicationBar with minimized mode override WebBrowser component at landscape orientation - c#

i have been read some similar questions on Stackoverflow but cannot make it works correctly
Here is my WebBrowser XAML code
<phone:WebBrowser Name="webBrowser"
ScriptNotify="webBrowser_ScriptNotify"
IsScriptEnabled="True"
Margin="0"
Background="Transparent"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
and Application Bar in code
void BuildAppBar()
{
ApplicationBar = new ApplicationBar();
ApplicationBar.Mode = ApplicationBarMode.Minimized;
...
}

This happens when you have set the Mode Property of ApplicationBar to Minimized (i don't know why), so what you can do is to use OrientationChanged event of the page to set the Mode Property:
private void PhoneApplicationPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
{
if (e.Orientation == PageOrientation.PortraitUp)
{
this.ApplicationBar.Mode = ApplicationBarMode.Minimized;
}
else
{
this.ApplicationBar.Mode = ApplicationBarMode.Default;
}
}

Related

How do I view TabView in Title Bar? In UWP WinUI 2 Application

I want to view TabView in title bar like image below.
I'm using UWP WinUI 2.
I'm trying to view my TabView in title bar. But TabView is viewing under title bar.
My MainPage.xaml code:
<muxc:TabView Grid.Row="2">
<muxc:TabViewItem Header="New Tab">
</muxc:TabViewItem>
</muxc:TabView>
This is actually pretty easy:
In your xaml code:
This piece of code adds a ShellTitlebarInset and a CustomDragRegion to the TabView. This is needed, to add a margin to the left and right side of the window.
<muxc:TabView x:Name="tabView">
<muxc:TabView.TabStripHeader>
<Grid x:Name="ShellTitlebarInset" Background="Transparent" />
</muxc:TabView.TabStripHeader>
<muxc:TabView.TabStripFooter>
<Grid x:Name="CustomDragRegion" MinWidth="188" Loaded="CustomDragRegion_Loaded" Background="Transparent" />
</muxc:TabView.TabStripFooter>
<muxc:TabViewItem Header="Tab1"/>
<muxc:TabViewItem Header="Tab2"/>
<muxc:TabViewItem Header="Tab3"/>
</muxc:TabView>
In your MainPage:
The LayoutMetricsChanged event handles the FlowDirection either from LeftToRight or RightToLeft to add the specific margin to the CustomDragRegion and ShellTitlebarInset.
private void CoreTitleBar_LayoutMetricsChanged(CoreApplicationViewTitleBar sender, object args)
{
if (FlowDirection == FlowDirection.LeftToRight)
{
CustomDragRegion.MinWidth = sender.SystemOverlayRightInset;
ShellTitlebarInset.MinWidth = sender.SystemOverlayLeftInset;
}
else
{
CustomDragRegion.MinWidth = sender.SystemOverlayLeftInset;
ShellTitlebarInset.MinWidth = sender.SystemOverlayRightInset;
}
CustomDragRegion.Height = ShellTitlebarInset.Height = sender.Height;
}
//Make sure to extend the view after the CustomDragRegion loaded, otherwise the tabs may clip under the minimize, maximize and close buttons of the window:
private void CustomDragRegion_Loaded(object sender, RoutedEventArgs e)
{
var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;
coreTitleBar.LayoutMetricsChanged += CoreTitleBar_LayoutMetricsChanged;
Window.Current.SetTitleBar(CustomDragRegion);
}
Here also the official documentation from Microsoft:
https://learn.microsoft.com/en-us/windows/apps/design/controls/tab-view

WPF - How to persist current content when setting the content property

I'm facing a problem where by setting the content property of my window I obviously remove pre-existing content. On all windows I have a dockpanel that I use to pop up help contextual help to the user but this is lost when I set the content property of the window. Therefore I will only see the content for the control I've added and pressing F1 does nothing as the dockpanel does not exist. I don't want to add this dockpanel to every control as it's poor code-reuse so what can I do to keep the dockpanel on the window and add content without overwriting original content of the window?
This is the code where I set the content of the window.
private void btnHelp_Click(object sender, RibbonControlEventArgs e)
{
System.Windows.Window window = new ResizeableWindow()
{
Title = "Help",
Content = new Controls.Help(),
ResizeMode = ResizeMode.NoResize
};
window.ShowDialog();
}
This is code for my Help control it's just a document viewer to read an xps document, this is used by the dockpanel.
public partial class Help : UserControl
{
public Help()
{
InitializeComponent();
string appPath = "path";
XpsDocument doc = new XpsDocument(appPath, FileAccess.Read);
var docx = doc.GetFixedDocumentSequence();
HelpDocViewer.Document = docx;
}
}
This is the xaml of my ResizableWindow containing the Dockpanel
<Window x:Class="Controls.ResizeableWindow"
KeyDown="HelpKeyListen">
<Grid>
<DockPanel x:Name="HelpPanel">
</DockPanel>
</Grid>
</Window>
Here is the code for the resizeable window
public ResizeableWindow()
{
InitializeComponent();
}
private void HelpKeyListen(object sender, KeyEventArgs e)
{
if (e.Key == Key.F1)
{
var HelpControl = new Help();
DockPanel.SetDock(HelpControl, Dock.Right);
HelpPanel.Children.Insert(0, HelpControl);
}
}
Use Placeholders inside the DockPanel instead of replacing the window content:
<DockPanel x:Name="HelpPanel">
<ContentControl x:Name="HelpContent" DockPanel.Dock="Right"/>
<ContentControl x:Name="MainContent"/>
</DockPanel>
Then assign the contents of the contentcontrols as needed
private void HelpKeyListen(object sender, KeyEventArgs e)
{
if (e.Key == Key.F1)
{
HelpContent.Content = new Help();
}
}
Possibly create a new dependency property in ResizeableWindow if you want to provide main content from the outside. Lets say you add a dependency property (visual studio code snipped propdp) named MainContent, then you can bind it as follows:
<DockPanel x:Name="HelpPanel">
<ContentControl x:Name="HelpContent" DockPanel.Dock="Right"/>
<ContentControl x:Name="MainContentPlaceholder" Content="{Binding MainContent,RelativeSource={RelativeSource AnchestorType=Window}}"/>
</DockPanel>
The more appropriate option would be to replace the MainContentPlaceholder by some more WPF/MVVM friendly way to display your contents, but thats out of scope for the question.

UserControl BringIntoView() not working properly

Background:
I have a usercontrol defined in a ScrollViewer along with a ContentControl, the ContentControl will be visible all the time, and within it there is a Button, when the button is clicked will set the usercontrol to Visible, and when the usercontrol shows (Visiblility="Visible") I want it to be scrolled into the view. I have
XAML
<ScrollViewer VerticalScrollBarVisibility="Auto" MaxHeight="465">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<ContentControl Content="{Binding MyOtherViewModel}" Width="960" ></ContentControl>
<local:MyView IsVisibleChanged="MyView_IsVisibleChanged" Grid.Row="1" Visibility="{Binding IsNonCompliant, Converter={StaticResource BooltoVisible}, UpdateSourceTrigger=PropertyChanged}" />
</ScrollViewer>
Code Behind
private void MyView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
(sender as Control).BringIntoView();
}
Problem: this is not working, or more precisely, my usercontrol scrolled into the view first then revert back to the bottom of the ScrollViewer in a blink.
Weird thing: show a messagebox before calling BringIntoView will correctly display my usercontrol into the middle of the view
Current hack solution: you can see this works even to close the Window immediately after its loaded
private void MyView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
Window ss = new Window();
ss.Loaded += new RoutedEventHandler(ss_Loaded);
ss.ShowDialog();
(sender as Control).BringIntoView();
}
private void ss_Loaded(object sender, RoutedEventArgs e)
{
(sender as Window).Close();
}
Question: I know there must be something else going on, but I just can't identify it, but I really want to know what happened when a window showing with ShowDialog? Is this because it refreshes the window so that the BringIntoView will happen only after the usercontrol been loaded? (Not as the problem I have now: BringIntoView happened first, and then the window get refreshed and put the scrollbar back to the top). And what is the correct fix for my problem?
It looks like BringIntoView called before my Usercontrol getting rendered, as a result when it gets fully rendered, the scrollbar is revert back to the top (as I have described in my question). And thanks for the answer from #Evgeny posted for another question, I get a better solution now (less hack maybe?). Still want to see if there are better solutions.
private void MyView_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var border = (FrameworkElement)sender;
if (border.IsVisible)
{
//Window ss = new Window();
//ss.Loaded += new RoutedEventHandler(ss_Loaded);
//ss.ShowDialog();
using (BackgroundWorker bg = new BackgroundWorker())
{
bg.DoWork += new DoWorkEventHandler(bg_DoWork);
bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg_RunWorkerCompleted);
Tuple<FrameworkElement, double> b = new Tuple<FrameworkElement, double>(border, border.Height);
bg.RunWorkerAsync(b);
}
}
}
private void bg_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
(e.Result as UserControl).BringIntoView();
}
private void bg_DoWork(object sender, DoWorkEventArgs e)
{
int maxwait = 300 //not scrolled to the view is not a disaster, but if the program hangs forever it will be a disaster, so set this to prevent that from happening
while (maxwait!=0
&&
(e.Argument as Tuple<FrameworkElement, double>).Item1.ActualHeight != (e.Argument as Tuple<FrameworkElement, double>).Item2)
{
Thread.Sleep(1);
maxwait --;
}
e.Result = (e.Argument as Tuple<FrameworkElement, double>).Item1;
}
I cannot believe that using background worker is a correct solution for this! You can use LayoutUpdated event to easily find when control is loaded and finally displayed.
userControl.LayoutUpdated+=OnLayoutUpdated;
private bool loaded=false;
private void OnLayoutUpdated(object sender,EventArgs e)
{
if (!loaded && (view.ActualHeight > 0 || view.ActualWidth > 0))
{
// Unsubscribe or set a flag.
userControl.LayoutUpdated -= OnLayoutUpdated;
loaded = true;
}
}
So you can execute that code when layout is updated and height or width is set. This will means that control is loaded and displayed.
Than you can unsubscribe or set a flag that initialization is complated.

toggle button visibility not working

I have a webbrowser that uses a simple forward and backward navigation scheme, and may also refresh or stop navigation if the user so choses. All navigation is working correctly, but my issue arises when I try to toggle the 'refresh' and 'stop' buttons depending on whether the webbrowser is Navigating or has Navigated. I would like for the refresh button to be set to visible as long as no navigation is occuring, and for the stop button to be set to visible while navigation is occuring. My basic implementation is as follows but I cannot seem to get the buttons to toggle from Visible to Collapsed depending on these scenarios.
MainPage.xaml
<Button x:Name="RefreshButton" Content="" Style="{StaticResource RefreshBtn}" Grid.Column="0" Grid.Row="0" Visibility="Visible" Click="RefreshButton_Click" toolkit:TiltEffect.IsTiltEnabled="True">
<Button x:Name="StopButton" Content="" Style="{StaticResource StopBtn}" Grid.Column="0" Grid.Row="0" Visibility="Collapsed" Click="StopButton_Click" toolkit:TiltEffect.IsTiltEnabled="True"/>
MainPage.xaml.cs
public MainPage()
{
InitializeComponent();
//Change Navigation buttons if the browser is currently Navigating
if (TheBrowser._IsNavigating == false)
{
RefreshButton.Visibility = Visibility.Visible;
StopButton.Visibility = Visibility.Collapsed;
}
else
{
RefreshButton.Visibility = Visibility.Collapsed;
StopButton.Visibility = Visibility.Visible;
}
//while (TheBrowser._IsNavigating == true)
//{
// RefreshButton.Visibility = Visibility.Collapsed;
// StopButton.Visibility = Visibility.Visible;
//}
}
WebBrowser.xaml.cs
//Flag to check if the browser is navigating
public bool _IsNavigating = false;
void TheWebBrowser_Navigating(object sender,
Microsoft.Phone.Controls.NavigatingEventArgs e)
{
_IsNavigating = true;
}
void TheWebBrowser_Navigated(object sender,
System.Windows.Navigation.NavigationEventArgs e)
{
_IsNavigating = false;
}
My WebBrowser.xaml.cs is a webbrowser user control which is embedded into MainPage.xaml and named TheBrowser. When debugging, I can see the changes in the bool variable _IsNavigating between true and false as shown above but this change is not detected in MainPage.xaml.cs which is why I think the button visibility does not change. Any help with this issue would be greatly appreciated.. I have run out of ideas of how to fix this! Thanks in advance.
The code for setting the visibility is in the wrong place, right now it is only called upon page construction.
You have to call the code whenever your _isNavigating variable changes.
Do the following:
void ChangeVisibility()
{
if (TheBrowser._IsNavigating == false)
{
RefreshButton.Visibility = Visibility.Visible;
StopButton.Visibility = Visibility.Collapsed;
}
else
{
RefreshButton.Visibility = Visibility.Collapsed;
StopButton.Visibility = Visibility.Visible;
}
}
void TheWebBrowser_Navigating(object sender,
Microsoft.Phone.Controls.NavigatingEventArgs e)
{
_IsNavigating = true;
ChangeVisibility();
}
void TheWebBrowser_Navigated(object sender,
System.Windows.Navigation.NavigationEventArgs e)
{
_IsNavigating = false;
ChangeVisibility();
}

First test of a Windows Phone application

I downloaded the Microsoft Visual Studio 2010 Express for Windows Phone and I wrote a simple application to make a first test of the emulator. In this application I have only a button with the property Content binded to a string called ButtonText and with the property Background binded to a SolidColorBrush named FillColor. I handled the Click event with this code:
void MyButton_Click(object sender, RoutedEventArgs e)
{
if (toggle == true)
{
ButtonText = "Blue";
FillColor = new SolidColorBrush(Colors.Blue);
}
else
{
ButtonText = "Red";
FillColor = new SolidColorBrush(Colors.Red);
}
toggle = !toggle;
}
Unfortunately this doesn't work. While the Content of the Button changes each time the button is pressed, I cannot say the same for the Background which remains at the same color.
Could you tell me what is wrong? Thank you.
I also post the XAML:
<Grid x:Name="ContentGrid" Grid.Row="1">
<Button Name="MyButton" Width="300" Height="300"
Content="{Binding Path=ButtonText}"
Background="{Binding Path=FillColor}" />
</Grid>
The issue is with the use of "new" in the line:
FillColor = new SolidColorBrush(Colors.Blue);
Using the "new" operation breaks the data binding that was previously set up. Try using the following instead:
FillColor.Color = Colors.Blue;
Replace both the changes to Blue and to Red and that should do the trick.
HTH!
Chris

Categories