2017-08-16 30 views
1

下面的ListView应调整其项目,至极呈现与一个TextBlock 的DataTemplate,通过降低字号。最初的FontSize在Style中指定,并且应该是最大值(23pt)。调整字号的ListViewItems当容器调整它的高度

如果项目文本变长,则它最多包含2行。

当窗口调整其高度或者控件的空间比显示项目所需的空间小时,字体大小应该减小,直到所有项目都可以显示。原包装文字应是“展开”如果可能的话

<ListView x:Name="myListView" Grid.Row="0" Grid.Column="0" 
        Background="White" BorderBrush="Black" BorderThickness="1" 
        IsHitTestVisible="False" 
        ScrollViewer.HorizontalScrollBarVisibility="Disabled" 
        ScrollViewer.VerticalScrollBarVisibility="Disabled"> 
      <ListView.ItemTemplate> 
       <DataTemplate> 
        <TextBlock MaxHeight="80" 
           Margin="0,0,0,21" 
           Text="{Binding}" 
           TextTrimming="CharacterEllipsis" 
           TextWrapping="Wrap"> 
         <TextBlock.Style> 
          <Style TargetType="{x:Type TextBlock}"> 
           <Setter Property="FontSize" Value="23pt" /> 
           <Setter Property="TextTrimming" Value="CharacterEllipsis" /> 
           <Setter Property="FontFamily" Value="Arial Regular" /> 
           <Setter Property="VerticalAlignment" Value="Center" /> 
           <Setter Property="HorizontalAlignment" Value="Left" /> 
          </Style> 
         </TextBlock.Style> 
        </TextBlock> 
       </DataTemplate> 
      </ListView.ItemTemplate> 
      <ListView.ItemContainerStyle> 
       ... 
      </ListView.ItemContainerStyle> 
     </ListView> 

Example Picture showing what i want enter image description here

我已经尝试过通过使用视框周围的ListView控件来实现的要求,但这将调整高度和宽度,以及(比)==>但文本的可用宽度应是恒定的。

另一种方法是为ListView重写MeasureOverride以减少FontSize,如果需要,控件的listView>可用大小的大小。但是这也没有奏效。

也许一些聪明的人可以帮助我解决这个问题。

最好的问候,

编辑2017年8月17日

我错过了一些必要的信息。 ListView中处于​​行= 0,列的网格内= 0:

<Grid.RowDefinitions> 
     <RowDefinition Height="*" /> 
     <RowDefinition Height="Auto" /> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="250" /> 
     <ColumnDefinition Width="300" /> 
    </Grid.ColumnDefinitions> 

的栅格单元0,0可以在高度只调整。 ListView将采用整个Cellsize并调整其子元素的FontSize以适应(对于可用的最大FontSize)。 将文本的包装为最多2个文本行也很重要。

+0

我我的答案更新了一些充分的工作代码。 –

回答

0

您可能需要做一些像绑定的FontSizeListView的宽度和使用自定义IValueConverter改变为FontSize是宽度,使文本放在一行。

不幸的是,没有内置的功能来做你想做的。


我现在有一个适用于您的工作解决方案!我不得不使用一些技巧来使这个工作。转换器需要能够看到关于ListView的更多信息,而不是它通常能够看到的。为了解决这个问题,我使用了一个IMultiValueConverter来发送整个ListView元素。它开始于MaxFontSize并下降一种字体大小,直到找到最长的一行完全符合LitView的宽度或者它到达MinFontSize的大小。

您可能需要做一些调整才能完美地满足您的需求,但这应该照顾最难的部分。您可能想要考虑优化大小代码,因为它可能会对很多项目产生性能问题。应该有几个相当明显的优化,我现在没有时间去做。

enter image description here

添加以下类:

class FontSizeConverter : FrameworkElement, IMultiValueConverter 
{ 
    public double MaxFontSize { get; set; } = 50; 
    public double MinFontSize { get; set; } = 1; 

    private Size MeasureString(string candidate, Typeface typeface, double fontSize, ListView listView) 
    { 
     var formattedText = new FormattedText(candidate, 
               CultureInfo.CurrentUICulture, 
               FlowDirection.LeftToRight, 
               typeface, 
               fontSize, 
               Brushes.Black, 
               VisualTreeHelper.GetDpi(listView).PixelsPerDip); 

     return new Size(formattedText.Width, formattedText.Height); 
    } 

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture) 
    { 
     var containerListView = values[1] as ListView; 
     if (containerListView == null || containerListView.ItemsSource==null) 
     { 
      return MaxFontSize; 
     } 

     Typeface typeface = new Typeface(containerListView.FontFamily, containerListView.FontStyle, containerListView.FontWeight, containerListView.FontStretch); 
     double size = MaxFontSize; 
     while (size > 0) 
     { 
      var biggestWidth = ((IEnumerable<string>)containerListView.ItemsSource).Select(s => MeasureString(s, typeface, size, containerListView).Width).Max(); 
      if (biggestWidth <= containerListView.ActualWidth) 
      { 
       return size; 
      } 
      size--; 
     } 
     return MinFontSize; 
    } 

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

使用此XAML:

<Window 
    x:Class="WpfApp4.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:local="clr-namespace:WpfApp4" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    xmlns:system="clr-namespace:System;assembly=mscorlib" 
    Title="MainWindow" 
    Width="525" 
    Height="350" 
    mc:Ignorable="d"> 
    <Window.Resources> 
     <x:Array x:Key="Data" Type="{x:Type system:String}"> 
      <system:String>Testing Testing Testing</system:String> 
      <system:String>Some more text Some more text Some more text</system:String> 
      <system:String>Longer text</system:String> 
      <system:String>text text text text text texttext text text text text text</system:String> 
      <system:String>Testing</system:String> 
     </x:Array> 
     <local:FontSizeConverter x:Key="FontSizeConverter" /> 
    </Window.Resources> 
    <ListView 
     Name="TheListView" 
     Margin="8" 
     ItemsSource="{Binding Source={StaticResource Data}}" 
     ScrollViewer.HorizontalScrollBarVisibility="Disabled"> 
     <ListView.FontSize> 
      <MultiBinding Converter="{StaticResource FontSizeConverter}"> 
       <Binding ElementName="TheListView" Path="ActualWidth" /> 
       <Binding ElementName="TheListView" /> 
      </MultiBinding> 
     </ListView.FontSize> 
     <ListView.Resources /> 
     <ListView.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding}" /> 
      </DataTemplate> 
     </ListView.ItemTemplate> 
    </ListView> 
</Window> 
+0

Thx为您提供帮助,但不幸的是,这不完全是我想要实现的。我用更多的信息编辑了我的问题。无论如何,我给你的解决方案尝试,并将“宽度”更改为“高度”。但是,当高度调整窗口大小时,ValueConverter(或ItemsSource Updated)不会被调用? – h4kun4m4t4t4