2015-06-24 2 views
1

Я разрабатываю браузер с несколькими вкладками, используя CefSharp. Код, который у меня сейчас, похож на пример wpf в github repo от CefSharp. Однако управление браузером работает неправильно. Он ничего не показывает. Пожалуйста помоги. Вы можете загрузить исходный код здесь enter link description hereCefSharp в TabControl не работает

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); 
     } 
    } 
} 

MainWindow.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> 

MainWindow.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> 

BrowserTabView.xaml.cs

using System.Windows.Controls; 

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

BrowserTabViewModel.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; 
     } 
    } 
} 

NonReloadingTabControl.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; 
     } 
    } 
} 
+0

Try копирование содержимого ваших файлов в верхней части примерных файлов проекта и использование git для сравнения различий ences. – amaitland

ответ

0

NonReloadingTabControl нуждается в индивидуальном стиле, см https://github.com/cefsharp/CefSharp/blob/master/CefSharp.Wpf.Example/App.xaml Или вы можете попробовать взломать 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; 
} 
Смежные вопросы