WPF webBrowser floating on all controls outside grid - c#

I have a webbrowser control and a canvas in grid row 0 & 1 receptively.
canvas have large picture and makes a horizontal scroll on grid.
So when i scroll down the webbrowser is floating on every control, where it should have scrolled within grid along canvas.
please guide what might be problem.
The code is here:
var wb = new WebBrowser();
wb.NavigateToString(#"<html><head><style> h1{color:red} </style></head><body>
<h-1>HTML code go here</h-1>
<h-1>HTML code go here</h-1>
</body></html>");
wb.Width = 700;
wb.Height = 200;
Grid.SetRow(wb, 0);
T1Grid.Children.Add(wb);
var imagePath = AppDomain.CurrentDomain.BaseDirectory + "images/Jellyfish.jpg";
var mainBitmap = new BitmapImage();
mainBitmap.BeginInit();
mainBitmap.UriSource = new Uri(#"" + imagePath, UriKind.RelativeOrAbsolute);
mainBitmap.EndInit();
_canvas = new Canvas
{
Width = mainBitmap.PixelWidth,
Height = mainBitmap.PixelHeight,
VerticalAlignment = VerticalAlignment.Top,
HorizontalAlignment = HorizontalAlignment.Left
};
var imageBrush = new Image { Source = mainBitmap };
_canvas.Children.Add(imageBrush);
Grid.SetRow(_canvas, 1);
T1Grid.Children.Add(_canvas);
xaml
<TabControl Grid.Row="1">
<TabItem Header="TabItem1">
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Grid x:Name="T1Grid" Background="Aqua">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
</Grid>
</ScrollViewer>
</TabItem>
<TabItem Header="TabItem2">
<Grid x:Name="T2Grid" Background="Aqua">
</Grid>
</TabItem>
<TabItem Header="TabItem3">
<Grid x:Name="T3Grid" Background="Aqua">
</Grid>
</TabItem>
</TabControl>

I had a look at your code and even tried replicating it in XAML, but there really is a problem there. Something is keeping the WebBrowser control at a certain size and somehow its z-index appears to always be on top.
After looking into it, I found out that it's because of the way it was implemented. From #SvenG's answer to the WPF c# webbrowser scrolls over top menu question here on Stack Overflow:
The WPF WebBrowser control is basically the old Win32 Webbrowser control and is technically rendered above the WPF content. Additionally it has some serious issues with size calculations.
The linked question also contains links to more information. Also see the links in the Why WPF WebBrowser Control is always on top ? post on the Visual Studio Forum for further information.

Related

WPF TabControl header issue

I am making an app in WPF that displays an image which can be dragged and zoomed. Bottom, right and upper sides contain some UI elements like buttons and in the center I have a TabControl to which I add TabItems in the code of ViewModel. These TabItems consists of their content (an image) and a header where I have tab buttons. The problem I have is that an image I drag covers the header but not the buttons as you can see on the screenshot. The behavior I expect is to have this image hidden underneath the entire header, not only buttons. It only happens with the bottom side. When I drag the image to the top or right it gets hidden behind the sides like it's supposed to.
Header issue
I tried to change its background, opacity and ZIndex but nothing worked for me.
Here is my code.
XAML:
<TabControl Grid.Row="1" Grid.Column="0" TabStripPlacement="Bottom" Background="LightGray" ItemsSource="{Binding LayoutTabs}"
SelectedIndex="0" SelectedItem="{Binding SelectedTab, Mode=OneWayToSource}"/>
C#:
LayoutTabs = new BindableCollection<TabItem>();
for (int i = 0; i < _content.LayoutImages.Count; i++)
{
DrawingImage drawing = _content.LayoutImages.ElementAt(i);
Image image = new Image() { Source = drawing };
image.MouseMove += OnMouseMove;
var container = new LayoutContainer()
{
Background = Brushes.WhiteSmoke,
Child = image,
Focusable = true,
};
var tabItem = new TabItem()
{
Header = _content.GetLayoutName(i),
Content = container
};
LayoutTabs.Add(tabItem);
}
That behaviour is due to the headerpanels background being set to transparent in the default control template. If you right click the tabcontrol in the Designer window (not xaml editor) and click on Edit Template->Edit a Copy you get a copy of that tempalte and can then modify the headerpanel with your BackgroundColor and if need be increase the Zindex:
[....]
//this is the line to make your changes on:
<TabPanel x:Name="headerPanel" Background="Transparent" Grid.Column="0" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>
[....]

Make XAML control with WebView full screen

Ultimate Goal
When a user clicks the Expand button, I want the WebContainerControl to be full screen, be focused, not allow scrolling in the ScrollViewer, and overlap the title grid (with the back button, page title, etc.)
Basically, it should be like clicking on a photo in a nice photo viewing app. Exapnd to full screen, have an X button in the top right corner and when you click it, it goes back to the regular view.
Problem
Since it's a WebView, I can't simply pass the view to a popup (It gives me an invalid args exception since the current browsing session can't be passed by reference... they logged in on a site, so it would be insecure I assume)
I have a XAML control with a webview in it:
<UserControl x:Class="App.WebContainerControl">
<Grid x:Name="grdWebContainer">
<StackPanel>
<Button Click="btnExpandView_Click"/>
<WebView x:Name="wvSite"/>
</StackPanel>
</Grid>
</UserControl>
Here is an example view it would be loaded into:
<Grid x:Name="grdMain">
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Title Grid -->
<Grid x:Name="grdTitleBar" Grid.Row="0">
<TextBlock Text="App Title"/>
</Grid>
<!-- Web Views -->
<Grid Grid.Row="1">
<ScrollViewer>
<StackPanel>
<controls:WebContainerControl x:Name="First Site"/>
<controls:WebContainerControl x:Name="Second Site"/>
</StackPanel>
</ScrollViewer>
</Grid>
</Grid>
What I have so far
So far, when they press the Expand button, it makes the control full screen (using Current.Window.Bounds)
Then, I pass the event that the button is pressed to the main view:
private void OnAccount_Expanded(object sender, ExpandedEventArgs args) {
// Expanded button is pressed and control is made full screen
if (args.IsExpanded) {
// Hide titlebar
grdMain.RowDefinitions[0].Height = GridLength.Auto;
grdTitleBar.Visibility = Windows.UI.Xaml.Visibility.Collapsed;
}
else {
// show titlebar again
GridLength gl = new GridLength(140);
grdMain.RowDefinitions[0].Height = gl;
grdTitleBar.Visibility = Windows.UI.Xaml.Visibility.Visible;
}
}
The Question
Right now, it makes it full screen, but I can still scroll. Any idea how to set the ScrollViewer to horizontally center on the control? If anyone has a better idea on how to achieve my Ultimate Goal, you would make me one happy camper! (Remember, it won't allow me to pass my control around, only manipulate it)
If I understand well, Put name on you Scroll Viewer
<ScrollViewer Name="uiScroll" >
............
</ScrollViewer >
When you doing full screen set visibility of you scrollBar
uiScroll.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;

Scrollbars in a dynamically filled stack panel

I am new for WPF so apologies if the answer is so obvious.
I got a WPF resizable window with a single stack panel control that is stretched vertically and horizontally to fill the window.
On window activated event, I use ".Children.Add" to add button controls to the panel. I have no idea how many buttons will be there at runtime so I checked "CanVerticallyScroll" in the panel. ScrollViewer.VerticalScrollBarVisibility is set to Visible by default.
I am still not seeing scroll bars at runtime though.
What properties did I miss to show scrolling panel with buttons?
Thanks
XAML:
<Window x:Class="ResMed.Ecp.Utility.ConnectionWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ConnectionWindow" Height="388" Width="641.6" Activated="Window_Activated">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="359*"/>
</Grid.RowDefinitions>
<StackPanel x:Name="pnlConnectionButtons" Margin="10,10.2,10.2,10" Grid.Row="1" CanVerticallyScroll="True"/>
</Grid>
</Window>
Code behind:
private void Window_Activated(object sender, EventArgs e)
{
for (int i = 0; i < 20; i++)
{
Button btn = new Button();
btn.Content = "Hello";
pnlConnectionButtons.Children.Add(btn);
}
}
Place your StackPanel inside a ScrollViewer:
<ScrollViewer>
<StackPanel>
<Button Content="Hello World"></Button>
...
...
</StackPanel>
</ScrollViewer>
You can also remove CanVerticallyScroll="True". From MSDN:
This property is not intended for use in your code. It is exposed publicly to fulfill an interface contract (IScrollInfo). Setting this property has no effect.

how to maintain the Width of tabItems should be equal in WPF?

how to maintain the width of the tabItems should be equal if i open multiple tabItems. know i am not getting this thing. i tried the following code
HorizontalContentAlignment="stretch"
i used the above code but it is not working. but i am getting like this
for tabcontrol i write the following code
<TabControl Name="tabControl1" Margin="175,44,0,0" >
<Grid></Grid>
</TabControl>
tabItems will dynamically adding to the Tabcontrol
TabItem tabitem2 = new TabItem();
Page2 pgobj1 = new Page2();
Frame tabframe1 = new Frame();
tabframe1.Content = pgobj1;
tabitem2.Header = "Tab 2Tab 2Tab 3";
tabitem2.Width = 300;
tabitem2.Content = tabframe1;
tabControl1.Items.Add(tabitem2);
tabitem2.IsSelected = true;
i don't want those spaces in between the tabItems. and they automatically resize if more number of tabs are opened. kindly help me out in this.
After removing the Hardcoded width property
it comes like this
Remove hardcoded width you are setting on TabItem. No need to set that, TabItem will automatically adjust its width base on header content.
tabitem2.Width = 300; // Remove this line
If you want items to come in single line and scroll using ScrollViewer, you need to modify Template of TabControl like mentioned here. I am posting the code from there for the sake of completeness of answer:
<TabControl Name="tabControl1">
<TabControl.Template>
<ControlTemplate TargetType="TabControl">
<StackPanel>
<ScrollViewer HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Disabled">
<TabPanel x:Name="HeaderPanel"
Panel.ZIndex ="1"
KeyboardNavigation.TabIndex="1"
Grid.Column="0"
Grid.Row="0"
Margin="2,2,2,0"
IsItemsHost="true"/>
</ScrollViewer>
<ContentPresenter x:Name="PART_SelectedContentHost"
SnapsToDevicePixels="{TemplateBinding
SnapsToDevicePixels}"
Margin="{TemplateBinding Padding}"
ContentSource="SelectedContent"/>
</StackPanel>
</ControlTemplate>
</TabControl.Template>
</TabControl>
Also check out this answer here.
If I understand you correctly, you want that all tab items should have equal width. You can achieve that by wrapping each tab item header inside a Grid with a ColumnDefinition that uses a SharedSizeGroup. Furthermore, you must mark the TabControl like this:
<TabControl x:Name="tabControl1" Grid.IsSharedSizeScope="True">
The following code shows how to set the Header property programmatically:
Grid grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition
{
SharedSizeGroup = "MySharedSizedGroupName",
Width = new GridLength(1.0, GridUnitType.Auto)
});
grid.Children.Add(new TextBlock{Text="Tab 5"});
tabitem2.Header = grid;
EDIT: And one other point: I think the <Grid></Grid> you have added as a child to the TabControl is unnecessary, because it creates that empty tab on the left side in the first tab row.

C# WPF add control to main window at run time

My goal is to attach a new image control while the application is running.
img = new System.Windows.Controls.Image();
img.Margin = new Thickness(200, 10, 0, 0);
img.Width = 32;
img.Height = 32;
img.Source = etc;
I've tried
this.AddChild(img);// says must be a single element
this.AddLogicalChild(img);// does nothing
this.AddVisualChild(img);// does nothing
It was never this difficult to add a element with forms.
How can I simply attach this new element to the main window (not another control) so that it will show up.
Solved it, I named the grid main, and from there I was able to access the children attribute and the add function
main.children.add(img);
<Window x:Class="Crysis_Menu.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" AllowsTransparency="False" Background="White" Foreground="{x:Null}" WindowStyle="SingleBorderWindow">
<Grid Name="main">
<Button Content="Run" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="btnRun" VerticalAlignment="Top" Width="151" Click="btnRun_Click" />
<TextBox Height="259" HorizontalAlignment="Left" Margin="12,40,0,0" Name="tbStatus" VerticalAlignment="Top" Width="151" />
</Grid>
</Window>
You should have only one root element under window. Adding the image using this.AddChilda adds the image as child of window, but you probably have some other child defined(Grid for example). Give a name to this child (Grid in the example) and then in the code behind add the image to the Grid
Example :
<Window>
<Grid x:Name="RootGrid">
</Grid>
</Window>
Then in the code behind use
RootGrid.Children.Add(img);
What is this in your case? You can try this.Content = image; or this.Children.Add(image);
If your this is indeed a Window, you should know that Window can have only a single child, which you put into Content. If you want several items in Window, usually you put some appropriate container (for example, Grid or StackPanel) as Window's content, and add children to it.
Vlad got the solution. I used it :
var grid = this.Content as Grid;
// or any controls
Label lblMessage = new Label
{
Content = "I am a label",
Margin = new Thickness(86, 269, 0, 0)
};
grid.Children.Add(lblMessage);

Categories

Resources