代码之家  ›  专栏  ›  技术社区  ›  ihatemash

如何将扩展器锚定到列表框的右侧?

  •  2
  • ihatemash  · 技术社区  · 16 年前

    <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 回复  |  直到 14 年前
        1
  •  2
  •   Sergey Aldoukhov    16 年前

    使用Expression Blend,编辑Expander的当前模板副本,转到模板的XAML,将“ExpanderLeftHeaderStyle”重命名为“ExpanderRightHeaderStyle”,将“ExtenderRightHeaderStyle“重命名为”ExpanderLeftHeaderStyle“。

        2
  •  2
  •   Ray Burns    16 年前

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

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

    将自动调整扩张器的其余部分以匹配。与“顶部”和“底部”对接相同。

    我实现DockedExpender是因为我讨厌将数百行WPF内部代码复制到我的项目中。此外,我的DockedExpander控件会自动适应新的主题样式,因为它读取WPF的内部样式。

    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)才能使用自定义控件。