2014-08-28 324 views
0

我複製了一個關於「WPF 4.5 Unleashed」ch.5。在示例中,碼頭設置在網格的右側因此,當在layer0.ColumnDefinitions.Add(column1CloneForLayer0);後面的代碼中調用時,將在網格的右側創建一個包含內容column1CloneForLayer0的列。 enter image description here如何正確使用ColumnDefinitions.Add?

在我的項目,我幾乎做了同樣的事情,但是當我調用該函數與一些內容添加一列,一些空的空間在右側創造的..這是不一樣expected.So什麼是正確的要做的事?
1.如何在網格左側添加一列?

2.在該示例中,該列已創建,但它爲什麼是空的?也許我需要設置Z指數?

enter image description here

更新 我加在原來的例子類似的東西在書上得到錯誤的結果。以下是源代碼。我只在左側添加了一個leftToolBoxhttps://www.dropbox.com/sh/61hm139j77kz9k1/AACKqhG5uXFkQgnt8fWi4NvNa?dl=0

UPDATE2 相關代碼:在這種情況下,我只是在左側添加一個StackPanel用按鈕,然後點擊呼叫DocakPane(3),而不是在左邊給新列,在正確的創建列。

public void DockPane(int paneNumber) 
{ 
    if (paneNumber == 1) 
    { 
     pane1Button.Visibility = Visibility.Collapsed; 
     pane1PinImage.Source = new BitmapImage(new Uri("pin.gif", UriKind.Relative)); 

     // Add the cloned column to layer 0: 
     layer0.ColumnDefinitions.Add(column1CloneForLayer0); 
     // Add the cloned column to layer 1, but only if pane 2 is docked: 
     if (pane2Button.Visibility == Visibility.Collapsed) layer1.ColumnDefinitions.Add(column2CloneForLayer1); 
    } 
    else if (paneNumber == 2) 
    { 
     pane2Button.Visibility = Visibility.Collapsed; 
     pane2PinImage.Source = new BitmapImage(new Uri("pin.gif", UriKind.Relative)); 

     // Add the cloned column to layer 0: 
     layer0.ColumnDefinitions.Add(column2CloneForLayer0); 
     // Add the cloned column to layer 1, but only if pane 1 is docked: 
     if (pane1Button.Visibility == Visibility.Collapsed) layer1.ColumnDefinitions.Add(column2CloneForLayer1); 
    } 
    else 
    { 
     leftpane1Button.Visibility = Visibility.Collapsed; 
     pane3PinImage.Source = new BitmapImage(new Uri("pin.gif", UriKind.Relative)); 
     layer0.ColumnDefinitions.Add(testcol); 

    } 
} 

enter image description here

+2

你要發佈一些代碼,你如何實現它。如果你不這樣做,我們只能打電話給我們的神奇奇蹟機器以確定出了什麼問題 – Mark 2014-08-28 06:55:01

+0

@Mark問題已更新。 – baozi 2014-08-28 07:24:39

+0

請僅在這裏發佈*相關*代碼。 – Sheridan 2014-08-28 07:57:11

回答

1

根據所提供的樣本項目,這裏是使用MVVM相同的重新寫入和最相關的硬編碼就都走了這個問題。它不是純MVVM,但主要是MVVM。

開始通過定義的ViewModels

一個類來表示塢窗格

class DockablePaneVM : ViewModelBase 
{ 
    public DockablePaneVM(DockHostVM host) 
    { 
     Host = host; 
    } 

    private string _title; 
    public string Title 
    { 
     get { return _title; } 
     set 
     { 
      _title = value; 
      RaisePropertyChanged("Title"); 
     } 
    } 

    private bool _isPinned; 
    public bool IsPinned 
    { 
     get { return _isPinned; } 
     set 
     { 
      _isPinned = value; 
      Host.PinModeChanged(this); 
      RaisePropertyChanged("IsPinned"); 
     } 
    } 

    private object _content; 
    public object Content 
    { 
     get { return _content; } 
     set 
     { 
      _content = value; 
      RaisePropertyChanged("Content"); 
     } 
    } 

    public DockHostVM Host { get; private set; } 
    public Dock Dock { get; set; } 
} 

主機爲dockpanes中,我使用的CollectionView爲了簡化位置

class DockHostVM : ViewModelBase 
{ 
    public DockHostVM() 
    { 
     Panes = new ObservableCollection<DockablePaneVM>(); 
     LeftPanes = new CollectionViewSource() { Source = Panes }.View; 
     RightPanes = new CollectionViewSource() { Source = Panes }.View; 
     FlotingLeftPanes = new CollectionViewSource() { Source = Panes }.View; 
     FlotingRightPanes = new CollectionViewSource() { Source = Panes }.View; 

     LeftPanes.Filter = o => Filter(o, Dock.Left, true); 
     RightPanes.Filter = o => Filter(o, Dock.Right, true); 
     FlotingLeftPanes.Filter = o => Filter(o, Dock.Left, false); 
     FlotingRightPanes.Filter = o => Filter(o, Dock.Right, false); 
    } 
    private bool Filter(object obj, Dock dock, bool isPinned) 
    { 
     DockablePaneVM vm = obj as DockablePaneVM; 
     return vm.Dock == dock && vm.IsPinned == isPinned; 
    } 

    public ObservableCollection<DockablePaneVM> Panes { get; set; } 

    public ICollectionView LeftPanes { get; set; } 
    public ICollectionView RightPanes { get; set; } 

    public ICollectionView FlotingLeftPanes { get; set; } 
    public ICollectionView FlotingRightPanes { get; set; } 

    private object _content; 

    public object Content 
    { 
     get { return _content; } 
     set { _content = value; } 
    } 

    public void PinModeChanged(DockablePaneVM paneVM) 
    { 
     LeftPanes.Refresh(); 
     RightPanes.Refresh(); 
     FlotingLeftPanes.Refresh(); 
     FlotingRightPanes.Refresh(); 
    } 

    //sample generator 
    public static DockHostVM GetSample() 
    { 
     DockHostVM vm = new DockHostVM(); 
     vm.Panes.Add(new DockablePaneVM(vm) { Title = "Left Toolbox", Content = new ToolBoxVM() }); 
     vm.Panes.Add(new DockablePaneVM(vm) { Title = "Solution Explorer", Content = new SolutionExplorerVM(), Dock = Dock.Right }); 
     vm.Panes.Add(new DockablePaneVM(vm) { Title = "Toolbox", Content = new ToolBoxVM(), Dock = Dock.Right }); 
     return vm; 
    } 
} 

然後樣式,以給予提供類的看法

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
        xmlns:l="clr-namespace:VisualStudioLikePanes"> 

    <DataTemplate DataType="{x:Type l:DockablePaneVM}"> 
     <Grid Grid.Column="1"> 
      <Grid.RowDefinitions> 
       <RowDefinition Height="auto" /> 
       <RowDefinition /> 
      </Grid.RowDefinitions> 
      <Grid.ColumnDefinitions> 
       <ColumnDefinition /> 
       <ColumnDefinition Width="auto" /> 
      </Grid.ColumnDefinitions> 
      <TextBlock Padding="8,4" 
         Text="{Binding Title}" 
         TextTrimming="CharacterEllipsis" 
         Background="{DynamicResource {x:Static SystemColors.ActiveCaptionBrushKey}}" 
         Foreground="{DynamicResource {x:Static SystemColors.ActiveCaptionTextBrushKey}}" /> 
      <ToggleButton IsChecked="{Binding IsPinned}" 
          Grid.Column="1"> 
       <Image Name="pinImage" 
         Source="pinHorizontal.gif" /> 
      </ToggleButton> 
      <ContentControl Content="{Binding Content}" 
          Grid.Row="1" 
          Grid.ColumnSpan="2" /> 
     </Grid> 
     <DataTemplate.Triggers> 
      <DataTrigger Binding="{Binding IsPinned}" 
         Value="True"> 
       <Setter Property="Source" 
         TargetName="pinImage" 
         Value="pin.gif" /> 
      </DataTrigger> 
     </DataTemplate.Triggers> 
    </DataTemplate> 

    <Style TargetType="TabItem"> 
     <Setter Property="Header" 
       Value="{Binding Title}" /> 
    </Style> 

    <Style TargetType="TabItem" 
      x:Key="FloterItem" 
      BasedOn="{StaticResource {x:Type TabItem}}"> 
     <Setter Property="LayoutTransform"> 
      <Setter.Value> 
       <RotateTransform Angle="90" /> 
      </Setter.Value> 
     </Setter> 
    </Style> 

    <Style TargetType="TabControl"> 
     <Setter Property="l:TabControlHelper.IsLastItemSelected" 
       Value="True" /> 
     <Style.Triggers> 
      <Trigger Property="HasItems" 
        Value="false"> 
       <Setter Property="Visibility" 
         Value="Collapsed" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 

    <Style TargetType="TabControl" 
      x:Key="AutoResizePane" 
      BasedOn="{StaticResource {x:Type TabControl}}"> 
     <Style.Triggers> 
      <Trigger Property="IsMouseOver" 
        Value="false"> 
       <Setter Property="Width" 
         Value="23" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 

    <DataTemplate DataType="{x:Type l:ToolBoxVM}"> 
     <ListBox Padding="10" 
       Grid.Row="1"> 
      <ListBoxItem>Button</ListBoxItem> 
      <ListBoxItem>CheckBox</ListBoxItem> 
      <ListBoxItem>ComboBox</ListBoxItem> 
      <ListBoxItem>Label</ListBoxItem> 
      <ListBoxItem>ListBox</ListBoxItem> 
     </ListBox> 
    </DataTemplate> 

    <DataTemplate DataType="{x:Type l:SolutionExplorerVM}"> 
     <TreeView Grid.Row="2"> 
      <TreeViewItem Header="My Solution" IsExpanded="True"> 
       <TreeViewItem Header="Project #1" /> 
       <TreeViewItem Header="Project #2" /> 
       <TreeViewItem Header="Project #3" /> 
      </TreeViewItem> 
     </TreeView> 
    </DataTemplate> 
</ResourceDictionary> 

我也創造了一些虛擬類來表示工具箱和解決方案資源管理器

也是一個輔助類,以提高我都用舉辦dockpanes標籤控件的可用性

class TabControlHelper 
{ 
    public static bool GetIsLastItemSelected(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(IsLastItemSelectedProperty); 
    } 

    public static void SetIsLastItemSelected(DependencyObject obj, bool value) 
    { 
     obj.SetValue(IsLastItemSelectedProperty, value); 
    } 

    // Using a DependencyProperty as the backing store for IsLastItemSelected. This enables animation, styling, binding, etc... 
    public static readonly DependencyProperty IsLastItemSelectedProperty = 
     DependencyProperty.RegisterAttached("IsLastItemSelected", typeof(bool), typeof(TabControlHelper), new PropertyMetadata(false, OnIsLastItemSelected)); 

    private static void OnIsLastItemSelected(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     TabControl tc = d as TabControl; 
     tc.Items.CurrentChanged += (ss, ee) => 
     { 
      if (tc.SelectedIndex < 0 && tc.Items.Count > 0) 
       tc.SelectedIndex = 0; 
     }; 

    } 
} 

這將讓任何時候選擇的項目,在這個項目中它將被用於當一個停靠窗格被固定/取消固定時

現在主窗口,請注意,我已經將停靠窗格限制爲4個選項卡控件,左,右,左浮動&右浮動

<Window x:Class="VisualStudioLikePanes.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     Title="MainWindow" 
     Height="500" 
     Width="800" 
     WindowStartupLocation="CenterScreen" 
     xmlns:l="clr-namespace:VisualStudioLikePanes"> 
    <Window.DataContext> 
     <ObjectDataProvider MethodName="GetSample" 
          ObjectType="{x:Type l:DockHostVM}" /> 
    </Window.DataContext> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="auto" /> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 
     <Menu> 
      <MenuItem Header="FILE" /> 
      ... 
      <MenuItem Header="HELP" /> 
     </Menu> 
     <DockPanel LastChildFill="True" 
        Grid.Row="1"> 

      <Border Width="23" 
        DockPanel.Dock="Left" 
        Visibility="{Binding Visibility, ElementName=LeftFloter}" /> 
      <Border Width="23" 
        DockPanel.Dock="Right" 
        Visibility="{Binding Visibility, ElementName=RightFloter}" /> 

      <TabControl ItemsSource="{Binding LeftPanes}" 
         DockPanel.Dock="Left" /> 

      <TabControl ItemsSource="{Binding RightPanes}" 
         DockPanel.Dock="Right" /> 

      <Grid Name="layer0"> 
       ... page content 
      </Grid> 
     </DockPanel> 
     <TabControl ItemsSource="{Binding FlotingLeftPanes}" 
        Grid.Row="1" 
        HorizontalAlignment="Left" 
        TabStripPlacement="Left" 
        Style="{StaticResource AutoResizePane}" 
        ItemContainerStyle="{StaticResource FloterItem}" 
        x:Name="LeftFloter" /> 

     <TabControl ItemsSource="{Binding FlotingRightPanes}" 
        Grid.Row="1" 
        HorizontalAlignment="Right" 
        TabStripPlacement="Right" 
        Style="{StaticResource AutoResizePane}" 
        ItemContainerStyle="{StaticResource FloterItem}" 
        x:Name="RightFloter" /> 
    </Grid> 
</Window> 

結果與MVVM方法您預期的行爲,增加新的面板很容易因爲Panes.Add(new DockablePaneVM(vm) { Title = "Left Toolbox", Content = new ToolBoxVM() });其餘部分被處理。

result

演示

下載工作樣例VisualStudioLikePanes.zip