I try to develop WebBrowser on c#, wpf and CefSharp for experience.
I use TabControl for tabs in WebBrowser.
So i add webbrowser to tabItem.Content but it dont showing up.
public partial class MainWindow : Window
{
ChromiumWebBrowser webBrowser;
public MainWindow()
{
//Browser init
CefSettings settings = new CefSettings();
Cef.Initialize(settings);
InitializeComponent();
textboxURL.Text = "https://www.google.com";
webBrowser = new ChromiumWebBrowser();
webBrowser.Load(textboxURL.Text);
tabItem1.Content = webBrowser;
}
//App Shutdown logic
private void Exit(object sender, StartupEventArgs e)
{
Cef.Shutdown();
}
}
This is XAML code. As you see i use DockPanel for topbar with URL and buttons.
And TabControl for tabs with browser. For now i use only one webBrowser for one tab.
Window x:Class="WebBrowser.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WebBrowser"
xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
mc:Ignorable="d"
Title="WebBrowser" Height="362" Width="699" WindowState="Maximized" WindowStartupLocation="CenterScreen">
<StackPanel HorizontalAlignment="Stretch" Margin="0,0,0,-1" Height="auto" VerticalAlignment="Stretch" >
<DockPanel VerticalAlignment="Top">
<Button x:Name="btnHome" Content="Home" Margin="2" DockPanel.Dock="Left"/>
<Button x:Name="btnBack" Content="Back" Margin="2" DockPanel.Dock="Left"/>
<Button x:Name="btnNext" Content="Next" Margin="2" DockPanel.Dock="Left"/>
<Label x:Name="labelHttp" Content="HTTP" DockPanel.Dock="Left"/>
<Button x:Name="btnMenu" Content="Menu" Margin="2" DockPanel.Dock="Right"/>
<Button x:Name="btnGo" Content="Go" Margin="2" DockPanel.Dock="Right"/>
<Button x:Name="btnRefresh" Content="Refresh" Margin="2" DockPanel.Dock="Right"/>
<TextBox x:Name="textboxURL" Margin="2"/>
</DockPanel>
<TabControl x:Name="tabControl1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0,5,0,0" Height="299">
<TabItem Header="TabPage" Name="tabItem1">
</TabItem>
</TabControl>
</StackPanel>
Ok, i try to use Address property then init browser and its load my url!
So answer is dont use webBrowser.Load(textboxURL.Text); on new element but use webBrowser.Address = textBoxURL.Text;
Thanks everyone!
--With CefSharp you can with this code--
public ChromiumWebBrowser drv;
string url = "https://www.example.com";
public void syhmhfzaddtab()
{
TabPage tb = new TabPage();
CefSettings settings = new CefSettings();
Cef.Initialize(settings);
drv = new ChromiumWebBrowser(url);
drv.Parent = tb;
tabControl1.Controls.Add(tb);
drv = new ChromiumWebBrowser(url);
drv.Dock = DockStyle.Fill;
}
Note:%100 a working code
Related
EDIT : My program doesn't start after adding the Background, and an icon to the program I added:
Icon="/assets/icon.ico"
Background="/assets/background.svg">
I checked if I had made a mistake but in my code everything is OK finally according to the IDE and according to me the beginner
Class MainWindow.xaml.cs :
using Avalonia.Controls;
using Avalonia.Interactivity;
namespace AvaloApp;
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void startButton(object sender, RoutedEventArgs e) {
Button start = new Button();
}
private void stopButton(object sender, RoutedEventArgs e) {
Button stop = new Button();
}
private void hotkeyButton(object sender, RoutedEventArgs e) {
Button hotkey = new Button();
}
}
Class MainWindow.xaml :
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="AvaloApp.MainWindow"
Title="AvaloApp"
Icon="/assets/icon.ico"
Background="/assets/background.svg">
<Grid>
<Button Grid.Column="1" Grid.Row="0" x:Name="start" Content="Start" Click="startButton" Margin="5" HorizontalContentAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Width="100" Height="50"/>
<Button Grid.Column="2" Grid.Row="0" x:Name="stop" Content="Stop" Click="stopButton" Margin="280,5,5,5" HorizontalContentAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Width="100" Height="50"/>
<Button Grid.Column="3" Grid.ColumnSpan="2" Grid.Row="1" x:Name="hotkey" Content="Hotkey" Click="hotkeyButton" Margin="5,140,5,5" HorizontalContentAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Width="200" Height="50"/>
</Grid>
</Window>
I tried to debug the program, it says that it does not find the icon, except that it is placed here in the project structure: https://i.imgur.com/Z7WTJmW.png (in the assets folder) and in my code I have specified the location
Even removing the / before assets still doesn't find the file, and surely prevents the project from running properly
The result is the same when I put the images like this: https://i.imgur.com/AdX5LWe.png
I would like to have a popup show at the bottom of each textbox in my window, as they are focused.
The user would be presented with the last few entries entered in that textbox. I would like the placement to be such that it would be at the bottom of the textbox currently focused.
This is my user control with the textbox:
<UserControl x:Class="PopupPlacement.MyControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<StackPanel>
<TextBox Name="TextBox_MyControl" Text="enter your text here" Height="25" Width="200"/>
</StackPanel>
</UserControl>
Here is my window:
<Window x:Class="PopupPlacement.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:PopupPlacement"
Title="MainWindow" Height="450" Width="800">
<Canvas>
<Grid ShowGridLines="False">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Label Content="Domain" Margin="10"/>
<local:MyControl Grid.Column="1" x:Name="Domain" Margin="10"/>
<Label Grid.Row="1" Content="Username" Margin="10"/>
<local:MyControl Grid.Row="1" Grid.Column="1" x:Name="Username" Margin="10"/>
<Label Grid.Row="2" Content="Password" Margin="10"/>
<local:MyControl Grid.Row="2" Grid.Column="1" x:Name="Password" Margin="10"/>
<Button Grid.Row="3" Content="OK" Margin="10" Name="Button_OK"/>
<Button Grid.Row="3" Grid.Column="1" Content="Cancel" Margin="10"/>
<Popup PlacementTarget="{Binding ElementName=TextBox_MyControl}" Placement="Bottom"
IsOpen="{Binding ElementName=TextBox_MyControl, Path=IsKeyboardFocused}">
<ComboBox IsDropDownOpen="True">
<ComboBoxItem IsSelected="True">Item 1</ComboBoxItem>
<ComboBoxItem>Item 2</ComboBoxItem>
</ComboBox>
</Popup>
</Grid>
</Canvas>
</Window>
Appreciate any pointers.
For me, the best solution to a similar requirement was to write a Behavior that kind of mimics Intellisense.
I don't have any simple code at hand, but you could create and show a ListBox inside a Popup placed at the AssociatedObject's bottom. You can then bind the TextBox-related entries to the Behavior via a DependencyProperty.
Of course, there's a lot more to it like closing the Popup, re-using existing controls, handling key presses to access the ListBox, insert the selected value to the TextBox etc.
Here's a simple (untested) sketch.
public class IntellisenseBehavior : Behavior<TextBox>
{
public IEnumerable ItemsSource
{
get => (IEnumerable)GetValue(ItemsSourceProperty);
set => SetValue(ItemsSourceProperty, value);
}
public static readonly DependencyProperty ItemsSourceProperty =
DependencyProperty.Register("ItemsSource", typeof(IEnumerable), typeof(IntellisenseBehavior), new UIPropertyMetadata(null));
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.GotKeyboardFocus += AssociatedObjectOnGotKeyboardFocus;
}
protected override void OnDetaching()
{
base.OnDetaching();
AssociatedObject.GotKeyboardFocus -= AssociatedObjectOnGotKeyboardFocus;
//cleanup
}
private void AssociatedObjectOnGotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
var popup = new Popup
{
ClipToBounds = false,
AllowsTransparency = true,
PopupAnimation = PopupAnimation.Fade,
HorizontalAlignment = HorizontalAlignment.Left
};
popup.SetValue(FocusManager.IsFocusScopeProperty, true);
popup.Placement = PlacementMode.Bottom;
popup.PlacementTarget = AssociatedObject;
var shadow = new SystemDropShadowChrome { Color = Colors.Transparent, MaxHeight = 200, Margin = new Thickness(0, 0, 5, 5) };
var listBox = new ListBox
{
ItemsSource = ItemsSource
}
((IAddChild)shadow).AddChild(listBox);
((IAddChild)popup).AddChild(shadow);
popup.IsOpen = true;
}
}
Attach it to all TextBoxes that you require to have this functionality and for instance use a converter to get the filtered entries you need.
<!-- Uses converter's public const string NameBox = "NameBox"; for filtering. -->
<TextBox>
<i:Interaction.Behaviors>
<IntellisenseBehavior ItemsSource="{Binding LastEntries, Converter={StaticResource FilterEntriesConverter}, ConverterParameter={x:Static FilterEntriesConverter.NameBox}}" />
</i:Interaction.Behaviors>
</TextBox>
Hope that helps.
I have a problem with ListView while the ContentControl it is in is hidden.
My program uses XMPP and updates when players connect to the Chat server. When the ContentControl is visible while someone connects it looks like this:
But if they connect and the ContentControl is invisible when it renders it looks like this (once set visible again):
However, if you hover in just the right spot you can see that the control is still there, just not rendered:
Here is my UserControl:
<UserControl x:Class="LegendaryClient.Controls.ChatPlayer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
Height="50" Width="250">
<Grid>
<Rectangle Fill="#02000000" />
<!-- Allow entire control to be hovered over -->
<Image x:Name="ProfileImage" HorizontalAlignment="Left" Height="40" Margin="5,5,0,0" VerticalAlignment="Top" Width="40" Source="/LegendaryClient;component/Icon.ico" />
<Label x:Name="LevelLabel" Content="30" HorizontalAlignment="Left" Margin="5,20,0,0" VerticalAlignment="Top" Foreground="White" FontWeight="SemiBold">
<Label.Effect>
<DropShadowEffect ShadowDepth="2" BlurRadius="1" />
</Label.Effect>
</Label>
<Label x:Name="PlayerName" Content="Snowl" HorizontalAlignment="Left" Margin="45,0,0,0" VerticalAlignment="Top" FontWeight="Bold" Foreground="White" />
<Label x:Name="PlayerStatus" Content="Test status" HorizontalAlignment="Left" Margin="45,20,0,0" VerticalAlignment="Top" Foreground="White" />
</Grid>
</UserControl>
And my render function:
if (Client.UpdatePlayers)
{
Client.UpdatePlayers = false;
ChatListView.Items.Clear();
foreach (KeyValuePair<string, ChatPlayerItem> ChatPlayerPair in Client.AllPlayers.ToArray())
{
if (ChatPlayerPair.Value.Level != 0)
{
ChatPlayer player = new ChatPlayer();
player.Width = 250;
player.Tag = ChatPlayerPair.Value;
player.PlayerName.Content = ChatPlayerPair.Value.Username;
player.LevelLabel.Content = ChatPlayerPair.Value.Level;
player.PlayerStatus.Content = ChatPlayerPair.Value.Status;
var uriSource = new Uri(Path.Combine(Client.ExecutingDirectory, "Assets", "profileicon", ChatPlayerPair.Value.ProfileIcon + ".png"), UriKind.RelativeOrAbsolute);
player.ProfileImage.Source = new BitmapImage(uriSource);
player.ContextMenu = (ContextMenu)Resources["PlayerChatMenu"];
player.MouseMove += ChatPlayerMouseOver;
player.MouseLeave += player_MouseLeave;
ChatListView.Items.Add(player);
}
}
}
I have a page containing two StackPanels, each containing one TextBox and one Button:
<StackPanel x:Name="Row1">
<TextBox x:Name="TextBox1" Text="" GotFocus="OnFocusHandler" LostFocus="OffFocusHandler"/>
<Button x:Name="Button1" Content="Convert" Click="OnClickHandler" Visibility="Collapsed"/>
</StackPanel>
<StackPanel x:Name="Row2">
<TextBox x:Name="TextBox2" Text="" GotFocus="OnFocusHandler" LostFocus="OffFocusHandler"/>
<Button x:Name="Button2" Content="Convert" Click="OnClickHandler" Visibility="Collapsed"/>
</StackPanel>
I would like to do the following:
When a textbox has focus, the other textbox must be hidden and the corresponding button must show
When a textbox is out of focus, we are back to the original display: only empty textboxes are visible
I don't want the button to be able to trigger the OffFocusHandler
This is the current code that I have for the three handlers:
private void OnFocusHandler(object sender, RoutedEventArgs e)
{
TextBox SenderTextBox = (TextBox)sender;
if (SenderPanel.Name == "TextBox1")
{
Button1.Visibility = Visibility.Visible;
}
else if (SenderPanel.Name == "TextBox2")
{
Button2.Visibility = Visibility.Visible;
}
}
private void OffFocusHandler(object sender, RoutedEventArgs e)
{
TextBox1.Text = "";
TextBox2.Text = "";
Button1.Visibility = Visibility.Collapsed;
Button2.Visibility = Visibility.Collapsed;
}
private void OnClickHandler(object sender, RoutedEventArgs e)
{
// some stuff unrelated to my issue
}
How do I avoid the button clicking to trigger the OffFocusHandler code?
Is there another way to code this? I'm a complete beginner so I may not think the right way.
You can just Bind to the TextBox.IsFocused property in Xaml, and use the BooleanToVisibilityConverter to show/hide the button.
Example:
<Window x:Class="WpfApplication4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication4"
Title="MainWindow" Height="300" Width="400" Name="UI" >
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolTovisible" />
</Window.Resources>
<Grid>
<StackPanel x:Name="Row1" Height="54" VerticalAlignment="Top">
<TextBox x:Name="TextBox1" Text="" />
<Button x:Name="Button1" Content="Convert" Visibility="{Binding ElementName=TextBox1, Path=IsFocused, Converter={StaticResource BoolTovisible}}"/>
</StackPanel>
<StackPanel x:Name="Row2" Margin="0,60,0,0" Height="51" VerticalAlignment="Top">
<TextBox x:Name="TextBox2" Text="" />
<Button x:Name="Button2" Content="Convert" Visibility="{Binding ElementName=TextBox2, Path=IsFocused, Converter={StaticResource BoolTovisible}}"/>
</StackPanel>
</Grid>
</Window>
for each element, there is a Visibility tag, it is "Visible" by default but you can assign "Hidden" or "Collapsed" as follow:
<RadioButton Margin="20,118,318,-43" GroupName="MCSites" Visibility="Hidden">
Radio Button Description
</RadioButton>
I got a strange problem. I have a tabcontrol and 3 tabs. On every tab i got a webbrowser control on it. They all navigate to a website. But it only navigates if you're actually looking at the webbrowser control. So having it minimized on taskbar or systray, wont make it navigate to a website.
Why is that? How can i change this behavior?
[EDIT]
This only seems to happen when i startup the app. After it got 'focus' or a 'look at', this doesn't happen anymore.
Some more info, the navigating happens from a different thread than the UI-thread.
[/EDIT]
[3nd EDIT]
Here is a test case:
XAML code:
<Window x:Class="WPFWebbrowserFocusTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="453" Width="755">
<Grid>
<TabControl Height="390" HorizontalAlignment="Left" Margin="12,12,0,0" Name="tabControl1" VerticalAlignment="Top" Width="709">
<TabItem Header="tabItem1" Name="tabItem1">
<Grid>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="18,17,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
</Grid>
</TabItem>
<TabItem Header="tabItem2" Name="tabItem2">
<Grid>
<WebBrowser Height="352" HorizontalAlignment="Left" Margin="0,6,0,0" Name="webBrowser1" VerticalAlignment="Top" Width="693" Navigated="webbrowser_Navigated" LoadCompleted="webbrowser_LoadCompleted" />
</Grid>
</TabItem>
<TabItem Header="tabItem3" Name="tabItem3">
<Grid>
<WebBrowser Height="346" HorizontalAlignment="Left" Margin="6,6,0,0" Name="webBrowser2" VerticalAlignment="Top" Width="687" Navigated="webbrowser_Navigated" LoadCompleted="webbrowser_LoadCompleted" />
</Grid>
</TabItem>
<TabItem Header="tabItem4" Name="tabItem4">
<Grid>
<WebBrowser Height="346" HorizontalAlignment="Left" Margin="10,10,0,0" Name="webBrowser3" VerticalAlignment="Top" Width="687" Navigated="webbrowser_Navigated" LoadCompleted="webbrowser_LoadCompleted" />
</Grid>
</TabItem>
<TabItem Header="tabItem5" Name="tabItem5">
<Grid>
<WebBrowser Height="346" HorizontalAlignment="Left" Margin="10,10,0,0" Name="webBrowser4" VerticalAlignment="Top" Width="687" Navigated="webbrowser_Navigated" LoadCompleted="webbrowser_LoadCompleted" />
</Grid>
</TabItem>
</TabControl>
</Grid>
Here is the code behind file:
public MainWindow()
{
InitializeComponent();
}
private void webbrowser_Navigated(object sender, NavigationEventArgs e)
{
this.SuppressScriptErrors((WebBrowser)sender, true);
}
private void webbrowser_LoadCompleted(object sender, NavigationEventArgs e)
{
WebBrowser wb = (WebBrowser)sender;
if (e.Uri.AbsoluteUri != wb.Source.AbsoluteUri)
return;
}
public void SuppressScriptErrors(System.Windows.Controls.WebBrowser wb, bool Hide)
{
FieldInfo fi = typeof(System.Windows.Controls.WebBrowser).GetField(
"_axIWebBrowser2", BindingFlags.Instance | BindingFlags.NonPublic);
if (fi != null)
{
object browser = fi.GetValue(wb);
if (browser != null)
{
browser.GetType().InvokeMember("Silent", BindingFlags.SetProperty, null, browser, new object[] { Hide });
}
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
this.webBrowser1.Navigate("http://www.google.com");
this.webBrowser2.Navigate("http://www.google.com");
this.webBrowser3.Navigate("http://www.google.com");
this.webBrowser4.Navigate("http://www.google.com");
}
How to reproduce:
Put a breakpoint inside webbrowser_LoadCompleted. Then press the button which is located on the first tabpage of the tabcontrol.
Dont go to the next tabpage yet, wait a coupled of seconds, like 15 or so.
Then go to tabitem2 or 3/4/5. You'll see that the page just got loaded and the webbrowser_LoadCompleted event got fired.
Here's a code fragment in WPF that works. Once you click the button, it minimizes the application, and after 2 seconds calls navigate to all browsers while the window is minimized. Pages are loaded in all tabs regardless of window state or tab focus.
Make sure are calling Navigate inside a Dispatcher.Invoke. You can't make UI changes in WPF from a different thread unless you call the dispatcher. That might be a problem.
My example below calls the navigation from a different thread.
<Window x:Class="WpfApplication3.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
DataContext="{Binding RelativeSource={RelativeSource Self}}"
Title="MainWindow" Height="350" Width="525"
StateChanged="Window_StateChanged">
<Grid>
<TabControl Height="225" HorizontalAlignment="Left" Margin="12,12,0,0" Name="tabControl1" VerticalAlignment="Top" Width="491">
<TabItem Header="tabItem1">
<WebBrowser Height="189" Name="webBrowser1" Width="479" />
</TabItem>
<TabItem Header="tabItem2">
<WebBrowser Height="185" Name="webBrowser2" Width="466" />
</TabItem>
<TabItem Header="tabItem3">
<WebBrowser Height="187" Name="webBrowser3" Width="434" />
</TabItem>
</TabControl>
<Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="116,268,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" />
<TextBox Height="23" HorizontalAlignment="Left" Margin="236,268,0,0" Name="textBox1" VerticalAlignment="Top" Width="120" />
</Grid>
</Window>
private void button1_Click(object sender, RoutedEventArgs e)
{
this.WindowState = System.Windows.WindowState.Minimized;
}
private void Window_StateChanged(object sender, EventArgs e)
{
if (this.WindowState == System.Windows.WindowState.Minimized)
{
new Thread((state) =>
{
Thread.Sleep(TimeSpan.FromSeconds(2));
this.Dispatcher.Invoke(new Action(() =>
{
webBrowser1.Navigate(textBox1.Text);
webBrowser2.Navigate(textBox1.Text);
webBrowser3.Navigate(textBox1.Text);
}), null);
}).Start();
}
}
It seems that this is the behavior of this control in WPF according to the docs.