2009-11-09 59 views
2

下面的XAML代碼工作正常,除了我想要擴展器按鈕之間的列表框和網格。如果我將ExpandDirection設置爲「Left」,則該按鈕位於列表框和網格之間,但按鈕上的方向指示器會讓用戶感到困惑 - 它在展開時指向右側,而在未展開時指向左側。我希望方向指示器按照ExpandDirection =「Right」的方式工作,但我希望ExpandDirection =「Left」的功能。如何將擴展器定位到ListBox的右側?

<DockPanel> 
    <Expander ExpandDirection="Right"> 
     <ListBox> 
      <ListBoxItem>Item One</ListBoxItem> 
      <ListBoxItem>Item Two</ListBoxItem> 
      <ListBoxItem>Item Three</ListBoxItem> 
      <ListBoxItem>Item Four</ListBoxItem> 
      <ListBoxItem>Item Five</ListBoxItem> 
     </ListBox> 
    </Expander> 
     <Grid Background="AliceBlue"> 
      <TextBlock > 
      Other Content 
      </TextBlock> 
     </Grid> 
</DockPanel> 

回答

2

使用Expression Blend中,編輯當前模板的副本的擴展,去XAML爲模板,重命名「ExpanderLeftHeaderStyle」到「ExpanderRightHeaderStyle」和「ExpanderRightHeaderStyle」到「ExpanderLeftHeaderStyle」。

+0

這樣做很有效,但它有將幾百行主題樣式XAML複製到項目中的缺點。這可能會使您的項目難以維護。它也有不處理未來主題變化的缺點。 – 2009-11-09 23:48:07

2

我更喜歡使用我寫回來的DockedExpander類(代碼如下)。這個類自動爲它停靠的DockPanel的任何一側設置它自己。

例如,在:

<DockPanel> 
    <edf:DockedExpander DockPanel.Dock="Left"> 
    <ListBox ... 
    </edf:DockedExpander> 

    <Grid ... 

</DockPanel> 

擴張器將左開,與朝向正確的按鈕。但將其更改爲:

<edf:DockedExpander DockPanel.Dock="Right"> 

將自動調整其餘的擴展器以匹配。與「頂部」和「底部」對接相同。

我實現了DockedExpander,因爲想將幾百行WPF的內部代碼複製到我的項目中對我來說是可惡的。此外,我的DockedExpander控件會自動適應新的主題樣式,因爲它讀取WPF的內部樣式。

下面是DockedExpander類的代碼:

public class DockedExpander : Expander 
{ 
    static DockedExpander() 
    { 
    _directions = new Dictionary<Dock, DirectionData>(); 
    _directions[Dock.Left] = new DirectionData { Reverse = Dock.Right, ExpandDirection = ExpandDirection.Right }; 
    _directions[Dock.Right] = new DirectionData { Reverse = Dock.Left, ExpandDirection = ExpandDirection.Left }; 
    _directions[Dock.Top] = new DirectionData { Reverse = Dock.Bottom, ExpandDirection = ExpandDirection.Down }; 
    _directions[Dock.Bottom] = new DirectionData { Reverse = Dock.Top, ExpandDirection = ExpandDirection.Up }; 

    DockPanel.DockProperty.OverrideMetadata(typeof(DockedExpander), new FrameworkPropertyMetadata 
    { 
     PropertyChangedCallback = (obj, e) => ((DockedExpander)obj).UpdateExpandDirection() 
    }); 

    ExpandDirectionProperty.OverrideMetadata(typeof(DockedExpander), new FrameworkPropertyMetadata 
    { 
     PropertyChangedCallback = (obj, e) => { throw new ArgumentException("Cannot set ExpandDirection because DockedExpander always computes its ExpandDirection from the DockPanel.Dock property"); } 
    }); 
    } 

    public override void OnApplyTemplate() 
    { 
    base.OnApplyTemplate(); 
    UpdateExpandDirection(); 
    } 

    private void UpdateExpandDirection() 
    { 
    // Can't use GetTemplateChild because non-PART_ names are not guaranteed to stay the same 
    var dockPanel = FindTwoElementDockPanelUnder(this); 
    var headerSite = dockPanel.Children[0]; 
    var expandSite = dockPanel.Children[1]; 

    // Compute the docking 
    Dock myDock = DockPanel.GetDock(this); 
    DirectionData myDockData = _directions[myDock]; 

    DockPanel.SetDock(headerSite, myDockData.Reverse); 
    DockPanel.SetDock(expandSite, myDock); 
    headerSite.SetValue(FrameworkElement.StyleProperty, myDockData.HeaderSiteStyle); 
    } 

    private static Dictionary<Dock, DirectionData> _directions; 
    private class DirectionData 
    { 
    public Dock Reverse; 
    public ExpandDirection ExpandDirection; 
    public Style HeaderSiteStyle 
    { 
     get 
     { 
     if(_headerSiteStyle==null) 
     { 
      var expander = new Expander { ExpandDirection = this.ExpandDirection }; 
      expander.BeginInit(); 
      expander.EndInit(); 
      expander.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity)); 
      var headerSite = FindTwoElementDockPanelUnder(expander).Children[0]; 
      _headerSiteStyle = ((FrameworkElement)headerSite).Style; 
     } 
     return _headerSiteStyle; 
     } 
    } 
    private Style _headerSiteStyle; 
    } 

    private static DockPanel FindTwoElementDockPanelUnder(DependencyObject visual) 
    { 
    while(true) 
     switch(VisualTreeHelper.GetChildrenCount(visual)) 
     { 
     case 1: visual = VisualTreeHelper.GetChild(visual, 0); continue; 
     case 2: return visual as DockPanel; 
     default: return null; 
     } 
    } 
} 

像往常一樣,你需要在你的XAML命名空間聲明(的xmlns),以便能夠使用自定義的控制。

相關問題