Wpf 弹性包装和织物修剪

Wpf 弹性包装和织物修剪,wpf,wrappanel,elasticlayout,texttrimming,Wpf,Wrappanel,Elasticlayout,Texttrimming,我试图创造一个弹性包装。 这意味着每一列都会拉伸自身以适应面板的宽度,直到新的列适合面板内部 列宽基于ItemMinWidth 我能够创建面板,但我的问题是如果我放置一个TextBlock并将TextTriming设置为CharacterEllipsis。在我的面板中,它不会工作。3个点不会出现。看起来列的宽度可以工作,但内容的宽度似乎是无穷大的 这是我的小组: using System; using System.Collections.Generic; using System.Compon

我试图创造一个弹性包装。 这意味着每一列都会拉伸自身以适应面板的宽度,直到新的列适合面板内部

列宽基于ItemMinWidth

我能够创建面板,但我的问题是如果我放置一个TextBlock并将TextTriming设置为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
    }
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用System.Linq;
使用System.Windows;
使用System.Windows.Controls;
命名空间包装测试
{
公共级弹性包装:面板
{
#区域构造函数
公共弹性包装纸()
{
}
#端区
#区域属性
[TypeConverter(typeof(LengthConverter))]
公共双项最小宽度
{
得到
{
返回(双精度)GetValue(ItemMinWidthProperty);
}
设置
{
SetValue(ItemMinWidthProperty,value);
}
}
公共静态只读DependencyProperty ItemMinWidthProperty=DependencyProperty.Register(“ItemMinWidth”、typeof(double)、typeof(ElasticWrapPanel));
[TypeConverter(typeof(LengthConverter))]
公共双栏宽
{
得到
{
返回(双精度)GetValue(ColumnWidthProperty);
}
专用设备
{
SetValue(ColumnWidthProperty,value);
}
}
公共静态只读DependencyProperty ColumnWidthProperty=DependencyProperty.Register(“ColumnWidth”、typeof(double)、typeof(ElasticWrapPanel));
#端区
#区域保护方法
受保护的覆盖尺寸测量覆盖(尺寸可用尺寸)
{
_uiElementsRect.Clear();
_columnCount=CalculateColumnCount(availableSize);
如果(_columnCount>0)
{
ColumnWidth=(int)Math.Floor(availableSize.Width/_columnCount);
双排高=0;
双lastRowHeight=0;
int currentColumn=0;
int currentRow=0;
foreach(InternalChildren中的UIElement子元素)
{
儿童。测量(可用性);
rowHeight=Math.Max(rowHeight,children.DesiredSize.Height);
Rect childrenRect=新的Rect(0,0,0,0);
childrenRect.X=当前列*列宽;
childrenRect.Y=最后一行高度;
childrenRect.Width=列宽;
childrenRect.Height=children.DesiredSize.Height;
_uiElementsRect.Add(children,childrenRect);
currentColumn++;
如果(currentColumn==\u columnCount)
{
lastRowHeight+=行高;
currentRow++;
行高=0;
currentColumn=0;
}
}
}
if(_uiElementsRect.Any())
{
double maxBottom=\u uiElementsRect.Max(ui=>ui.Value.Bottom);
返回新大小(availableSize.Width,maxBottom);
}
其他的
返回基准。测量超越(可用尺寸);
}
受保护的替代尺寸排列替代(尺寸最终化)
{
如果(_columnCount>0)
foreach(KeyValuePair KeyValuePair in _uiElementsRect)
keyValuePair.Key.Arrange(keyValuePair.Value);
返回基数。安排覆盖(最终化);
}
#端区
#区域私有方法
私有int CalculateColumnCount(可用大小大小大小)
{
if(ItemMinWidth==0 | | Double.IsNaN(ItemMinWidth)| | Double.IsInfinity(availableSize.Width))
返回0;
其他的
返回(int)数学地板(availableSize.Width/ItemMinWidth);
}
#端区
#区域私人成员
int _columnCount=0;
IDictionary _uiElementsRect=新字典();
#端区
}
}
这里有一个例子,与使用文本修剪的包装纸相比:

<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个点出现在每个元素的末尾,但不在我的面板中。

您的文本块没有设置大小,因此允许拉伸到它们想要的宽度

作为另一种选择,考虑限制它们的大小在<代码>测量覆盖> <代码>方法< /p>

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

    ((FrameworkElement)children).MaxWidth = ColumnWidth;

    // Other code
}