2011-09-28 34 views
0

我正在尝试创建Elastic WrapPanel。 这意味着每个色谱柱都会伸展自己以适应面板的宽度,直到新色谱柱适合面板内部。Elastic WrapPanel和TextTrimming

列宽基于ItemMinWidth。

我能够创建面板,但我的问题是,如果我把一个TextBlock并将TextTrimming设置为CharacterEllipsis。在我的面板中它不会工作。 3个点不会出现。它看起来像列的宽度工作,但内容似乎接收无限宽度。

这里是我的面板:

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Linq; 
using System.Windows; 
using System.Windows.Controls; 

namespace WrapPanelTest 
{ 
    public class ElasticWrapPanel : Panel 
    { 
     #region Constructor 

     public ElasticWrapPanel() 
     { 
     } 

     #endregion 

     #region Properties 

     [TypeConverter(typeof(LengthConverter))] 
     public double ItemMinWidth 
     { 
      get 
      { 
       return (double)GetValue(ItemMinWidthProperty); 
      } 
      set 
      { 
       SetValue(ItemMinWidthProperty, value); 
      } 
     } 

     public static readonly DependencyProperty ItemMinWidthProperty = DependencyProperty.Register("ItemMinWidth", typeof(double), typeof(ElasticWrapPanel)); 

     [TypeConverter(typeof(LengthConverter))] 
     public double ColumnWidth 
     { 
      get 
      { 
       return (double)GetValue(ColumnWidthProperty); 
      } 
      private set 
      { 
       SetValue(ColumnWidthProperty, value); 
      } 
     } 

     public static readonly DependencyProperty ColumnWidthProperty = DependencyProperty.Register("ColumnWidth", typeof(double), typeof(ElasticWrapPanel)); 

     #endregion 

     #region Protected methods 

     protected override Size MeasureOverride(Size availableSize) 
     { 
      _uiElementsRect.Clear(); 
      _columnCount = CalculateColumnCount(availableSize); 

      if (_columnCount > 0) 
      { 
       ColumnWidth = (int)Math.Floor(availableSize.Width/_columnCount); 
       double rowHeight = 0; 
       double lastRowHeight = 0; 
       int currentColumn = 0; 
       int currentRow = 0; 

       foreach (UIElement children in InternalChildren) 
       { 
        children.Measure(availableSize); 

        rowHeight = Math.Max(rowHeight, children.DesiredSize.Height); 

        Rect childrenRect = new Rect(0, 0, 0, 0); 
        childrenRect.X = currentColumn * ColumnWidth; 
        childrenRect.Y = lastRowHeight; 
        childrenRect.Width = ColumnWidth; 
        childrenRect.Height = children.DesiredSize.Height; 

        _uiElementsRect.Add(children, childrenRect); 

        currentColumn++; 

        if (currentColumn == _columnCount) 
        { 
         lastRowHeight += rowHeight; 
         currentRow++; 
         rowHeight = 0; 
         currentColumn = 0; 
        } 
       } 
      } 

      if (_uiElementsRect.Any()) 
      { 
       double maxBottom = _uiElementsRect.Max(ui => ui.Value.Bottom); 

       return new Size(availableSize.Width, maxBottom); 
      } 
      else 
       return base.MeasureOverride(availableSize); 
     } 

     protected override Size ArrangeOverride(Size finalSize) 
     { 
      if (_columnCount > 0) 
       foreach (KeyValuePair<UIElement, Rect> keyValuePair in _uiElementsRect) 
        keyValuePair.Key.Arrange(keyValuePair.Value); 

      return base.ArrangeOverride(finalSize); 
     } 

     #endregion 

     #region Private methods 

     private int CalculateColumnCount(Size availableSize) 
     { 
      if (ItemMinWidth == 0 || Double.IsNaN(ItemMinWidth) || Double.IsInfinity(availableSize.Width)) 
       return 0; 
      else 
       return (int)Math.Floor(availableSize.Width/ItemMinWidth); 
     } 

     #endregion 

     #region Private members 

     int _columnCount = 0; 

     IDictionary<UIElement, Rect> _uiElementsRect = new Dictionary<UIElement, Rect>(); 

     #endregion 
    } 
} 

而这里的个例,相比WrapPanel中的TextTrimming工作:

<Window x:Class="WrapPanelTest.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WrapPanelTest" 
     Title="MainWindow" 
     Height="480" 
     Width="640"> 

    <Window.Resources> 

     <Style x:Key="TextBlockStyle" TargetType="{x:Type TextBlock}"> 
      <Setter Property="Text" Value="Lorem ipsum dolor sit amet, consectetur adipiscing elit."/> 
      <Setter Property="TextTrimming" Value="CharacterEllipsis"/> 
      <Setter Property="Margin" Value="1"/> 
      <Setter Property="Background" Value="Silver"/> 
     </Style> 

    </Window.Resources> 

    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition/> 
      <RowDefinition/> 
     </Grid.RowDefinitions> 

     <WrapPanel ItemWidth="200"> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
     </WrapPanel> 

     <local:ElasticWrapPanel ItemMinWidth="200" Grid.Row="1"> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
      <TextBlock Style="{StaticResource TextBlockStyle}"/> 
     </local:ElasticWrapPanel> 

    </Grid> 
</Window> 

你应该看到,在WrapPanel 3点出现在最后每个元素,但不是在我的面板。

回答

1

您的TextBlocks没有设置大小,因此可以随意伸展。

作为替代方案,考虑限制在MeasureOverride方法大小

foreach (UIElement children in InternalChildren) 
{ 
    children.Measure(availableSize); 

    ((FrameworkElement)children).MaxWidth = ColumnWidth; 

    // Other code 
}