Tab控件中的CefSharp不显示任何内容。

问题描述 投票:1回答:1

我正在用CefSharp开发一个多标签浏览器。我现在的代码和CefSharp的github repo中的wpf例子类似。然而,浏览器控件不能正常工作。它不显示任何东西。请帮助我。你可以下载源代码 此处.

App.xaml

<Application x:Class="WpfApplication1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:view="clr-namespace:WpfApplication1.Views"
    xmlns:viewModel="clr-namespace:WpfApplication1.ViewModels"
    StartupUri="MainWindow.xaml">
    <Application.Resources>
        <DataTemplate DataType="{x:Type viewModel:BrowserTabViewModel}">
            <view:BrowserTabView />
        </DataTemplate>
    </Application.Resources>
</Application>

App.xaml.cs

using System.Windows;
namespace WpfApplication1
{
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            CefSharp.Cef.Initialize(new CefSharp.CefSettings());
            base.OnStartup(e);
        }
    }
}

主窗口.xaml

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:controls="clr-namespace:WpfApplication1.Controls"
        xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
        Title="MainWindow" Height="350" Width="525">
    <DockPanel>
        <Menu DockPanel.Dock="Top">
            <MenuItem Header="Google" Command="New" CommandParameter="http://google.com"></MenuItem>
        </Menu>
        <controls:NonReloadingTabControl
            x:Name="TabControl"
            Margin="0,5,0,0"
            ItemsSource="{Binding BrowserTabs, Mode=OneWay, UpdateSourceTrigger=PropertyChanged}"
            SelectedIndex="0">
            <TabControl.ItemTemplate>
                <DataTemplate>
                    <StackPanel Orientation="Horizontal">
                        <TextBlock Text="{Binding Title}"/>
                        <Button Content="X"
                                Height="20"
                                Width="20"
                                FontFamily="Courier"
                                FontWeight="Bold"
                                Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}"
                                Command="Close"
                                FontSize="10"
                                Padding="0"
                                Margin="10,0,0,0"
                                ToolTip="Close"/>
                    </StackPanel>
                </DataTemplate>
            </TabControl.ItemTemplate>
            <TabControl.ContentTemplate>
                <DataTemplate>
                    <ContentControl Content="{Binding}" />
                </DataTemplate>
            </TabControl.ContentTemplate>
        </controls:NonReloadingTabControl>
    </DockPanel>
</Window>

主窗口.xaml.cs

using System.Collections.ObjectModel;
using System.Windows;
using System.Windows.Input;
using WpfApplication1.ViewModels;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public ObservableCollection<BrowserTabViewModel> BrowserTabs { get; set; }

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

            BrowserTabs = new ObservableCollection<BrowserTabViewModel>();
            CommandBindings.Add(new CommandBinding(ApplicationCommands.New, OpenNewTab));
            CommandBindings.Add(new CommandBinding(ApplicationCommands.Close, CloseTab));
        }

        private void CloseTab(object sender, ExecutedRoutedEventArgs e)
        {
            if (BrowserTabs.Count > 0)
            {
                //Obtain the original source element for this event
                var originalSource = (FrameworkElement)e.OriginalSource;

                BrowserTabViewModel browserViewModel = null;

                if (originalSource is MainWindow)
                {
                    browserViewModel = BrowserTabs[TabControl.SelectedIndex];
                    BrowserTabs.RemoveAt(TabControl.SelectedIndex);
                }
                else
                {
                    //Remove the matching DataContext from the BrowserTabs collection
                    browserViewModel = (BrowserTabViewModel)originalSource.DataContext;
                    BrowserTabs.Remove(browserViewModel);
                }

                browserViewModel.WebBrowser.Dispose();
            }
        }

        private void OpenNewTab(object sender, ExecutedRoutedEventArgs e)
        {
            CreateNewTab((string)e.Parameter);
            TabControl.SelectedIndex = TabControl.Items.Count - 1;
        }

        private void CreateNewTab(string url = "about:blank")
        {
            BrowserTabs.Add(new BrowserTabViewModel(url));
        }
    }
}

BroswerTabView.xaml。

<UserControl x:Class="WpfApplication1.Views.BrowserTabView"
             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"
             xmlns:cefSharp="clr-namespace:CefSharp.Wpf;assembly=CefSharp.Wpf"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <DockPanel>
        <StatusBar DockPanel.Dock="Bottom">
            <ProgressBar
                HorizontalAlignment="Right"
                IsIndeterminate="{Binding WebBrowser.IsLoading}"
                Width="100"
                Height="16"
                Margin="3" />
        </StatusBar>
        <cefSharp:ChromiumWebBrowser
            Address="{Binding Address, Mode=TwoWay}"
            Title="{Binding Title, Mode=OneWayToSource}"
            WebBrowser="{Binding WebBrowser, Mode=OneWayToSource}" />
    </DockPanel>
</UserControl>

浏览器TabView.xaml.cs。

using System.Windows.Controls;

namespace WpfApplication1.Views
{
    /// <summary>
    /// Interaction logic for BrowserTabView.xaml
    /// </summary>
    public partial class BrowserTabView : UserControl
    {
        public BrowserTabView()
        {
            InitializeComponent();
        }
    }
}

BrowserTabView.xaml.cs

using CefSharp.Wpf;
using GalaSoft.MvvmLight;

namespace WpfApplication1.ViewModels
{
    public class BrowserTabViewModel : ViewModelBase
    {
        private string address;
        public string Address
        {
            get { return address; }
            set { Set(ref address, value); }
        }

        private string title;
        public string Title
        {
            get { return title; }
            set { Set(ref title, value); }
        }

        private IWpfWebBrowser webBrowser;
        public IWpfWebBrowser WebBrowser
        {
            get { return webBrowser; }
            set { Set(ref webBrowser, value); }
        }

        public BrowserTabViewModel(string address)
        {
            Address = address;
        }
    }
}

非重载标签控件.cs.

using System;
using System.Collections.Specialized;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace WpfApplication1.Controls
{
    [TemplatePart(Name = "PART_ItemsHolder", Type = typeof(Panel))]
    public class NonReloadingTabControl : TabControl
    {
        private Panel itemsHolderPanel;

        public NonReloadingTabControl()
        {
            // This is necessary so that we get the initial databound selected item
            ItemContainerGenerator.StatusChanged += ItemContainerGeneratorStatusChanged;
        }

        /// <summary>
        /// If containers are done, generate the selected item
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ItemContainerGeneratorStatusChanged(object sender, EventArgs e)
        {
            if (ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
            {
                ItemContainerGenerator.StatusChanged -= ItemContainerGeneratorStatusChanged;
                UpdateSelectedItem();
            }
        }

        /// <summary>
        /// Get the ItemsHolder and generate any children
        /// </summary>
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            itemsHolderPanel = GetTemplateChild("PART_ItemsHolder") as Panel;
            UpdateSelectedItem();
        }

        /// <summary>
        /// When the items change we remove any generated panel children and add any new ones as necessary
        /// </summary>
        /// <param name="e"></param>
        protected override void OnItemsChanged(NotifyCollectionChangedEventArgs e)
        {
            base.OnItemsChanged(e);

            if (itemsHolderPanel == null)
                return;

            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Reset:
                    itemsHolderPanel.Children.Clear();
                    break;

                case NotifyCollectionChangedAction.Add:
                case NotifyCollectionChangedAction.Remove:
                    if (e.OldItems != null)
                    {
                        foreach (var item in e.OldItems)
                        {
                            var cp = FindChildContentPresenter(item);
                            if (cp != null)
                                itemsHolderPanel.Children.Remove(cp);
                        }
                    }

                    // Don't do anything with new items because we don't want to
                    // create visuals that aren't being shown

                    UpdateSelectedItem();
                    break;

                case NotifyCollectionChangedAction.Replace:
                    throw new NotImplementedException("Replace not implemented yet");
            }
        }

        protected override void OnSelectionChanged(SelectionChangedEventArgs e)
        {
            base.OnSelectionChanged(e);
            UpdateSelectedItem();
        }

        private void UpdateSelectedItem()
        {
            if (itemsHolderPanel == null)
                return;

            // Generate a ContentPresenter if necessary
            var item = GetSelectedTabItem();
            if (item != null)
                CreateChildContentPresenter(item);

            // show the right child
            foreach (ContentPresenter child in itemsHolderPanel.Children)
                child.Visibility = ((child.Tag as TabItem).IsSelected) ? Visibility.Visible : Visibility.Collapsed;
        }

        private ContentPresenter CreateChildContentPresenter(object item)
        {
            if (item == null)
                return null;

            var cp = FindChildContentPresenter(item);

            if (cp != null)
                return cp;

            var tabItem = item as TabItem;
            cp = new ContentPresenter
            {
                Content = (tabItem != null) ? tabItem.Content : item,
                ContentTemplate = this.SelectedContentTemplate,
                ContentTemplateSelector = this.SelectedContentTemplateSelector,
                ContentStringFormat = this.SelectedContentStringFormat,
                Visibility = Visibility.Collapsed,
                Tag = tabItem ?? (this.ItemContainerGenerator.ContainerFromItem(item))
            };
            itemsHolderPanel.Children.Add(cp);
            return cp;
        }

        private ContentPresenter FindChildContentPresenter(object data)
        {
            if (data is TabItem)
                data = (data as TabItem).Content;

            if (data == null)
                return null;

            if (itemsHolderPanel == null)
                return null;

            foreach (ContentPresenter cp in itemsHolderPanel.Children)
            {
                if (cp.Content == data)
                    return cp;
            }

            return null;
        }

        protected TabItem GetSelectedTabItem()
        {
            var selectedItem = SelectedItem;
            if (selectedItem == null)
                return null;

            var item = selectedItem as TabItem ?? ItemContainerGenerator.ContainerFromIndex(SelectedIndex) as TabItem;

            return item;
        }
    }
}
c# wpf xaml cefsharp
1个回答
1
投票

NonReloadingTabControl 需要一个自定义的样式,见 https:/github.comcefsharpCefSharpblobmasterCefSharp.Wpf.Examl。 或者你可以试试黑客 NonReloadingTabControl.OnApplyTemplate() 如果你不想重新定义样式

/// <summary>
/// Get the ItemsHolder and generate any children
/// </summary>
public override void OnApplyTemplate()
{
    base.OnApplyTemplate();
    itemsHolderPanel = new Grid();
    // exchange ContentPresenter for Grid
    var topGrid = (Grid)GetVisualChild(0);
    var border = (Border)topGrid.Children[1];
    border.Child = itemsHolderPanel;
    UpdateSelectedItem();
}

/// <summary>
/// Create Grid in code behind instead of defining own style.
/// </summary>
private Grid CreateGrid()
{
    var grid = new Grid();
    Binding binding = new Binding(PaddingProperty.Name);
    binding.Source = this;  // view model?
    grid.SetBinding(Grid.MarginProperty, binding);

    binding = new Binding(SnapsToDevicePixelsProperty.Name);
    binding.Source = this;  // view model?
    grid.SetBinding(Grid.SnapsToDevicePixelsProperty, binding);

    return grid;
}
© www.soinside.com 2019 - 2024. All rights reserved.