2013-12-12 47 views
3

我有以下布局(简化的):因为它需要的ScrollViewer和TextBlock的包装

<Grid> 
    <Grid.ColumnDefinitions> 
    <ColumnDefinition MaxWidth="400" /> 
    <ColumnDefinition /> 
    </Grid.ColumnDefinitions> 

    <!-- Code for Column=0 --> 

    <ScrollViewer Grid.Column="1"> 
    <Grid x:Name="layoutGrid"> 

     <Grid.ColumnDefinitions> 
     <Grid.ColumnDefinition Width="Auto" /> 
     <Grid.ColumnDefinition MinWidth="100" MaxWidth="400" /> 
     <Grid.ColumnDefinition Width="Auto" /> 
     </Grid.ColumnDefinitions> 

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


     <!-- Code for Row=0 and Row=1 --> 

     <GroupBox Grid.ColumnSpan="3" Grid.Row=2> 
     <TextBlock Text="{Binding ...}" TextWrapping="Wrap" HorizontalAlignment="Left" VerticalAlignment="Top" /> 
     </GroupBox> 
    </Grid> 
    </ScrollViewer> 
</Grid> 
  • 第一列应占据空间作为糊状(有时也可以是100个像素,有时500)。
  • 第二列应伸展到可用空间,但不超过400像素(变丑)。
  • 第三列应该占用空间尽可能多(有时可以是200像素,有时可以是400)。
  • 如果在某些极少数情况下,layoutGrid需要的空间超过屏幕上可用的空间,则应该可以看到水平滚动条。
  • GroupBox应该始终具有全部三列的总宽度(它应该扩展到其宽度总数)。在那个空间中,文本框应该包裹起来。 GroupBox不应伸展到屏幕上可用的整个空间。

我该如何在xaml中实现这个功能?看起来只要插入ScrollViewer,TextBlock就不会再包装了。

回答

5

只要给TextBlock一个MaxWidth其为任一GroupBox或你的情况ActualWidthlayoutGrid(作为GroupBox具有相同的宽度)。这会迫使TextBlock必须在Width超过该维度时才换行,从而为您提供您的要求。

因此,像:

<GroupBox x:Name="grpBox" 
      Grid.Row="2" 
      Grid.ColumnSpan="3"> 
    <TextBlock MaxWidth="{Binding ElementName=grpBox, 
           Path=ActualWidth}" 
       HorizontalAlignment="Left" 
       VerticalAlignment="Top" 
       Text="{Binding ...}" 
       TextWrapping="Wrap" /> 
</GroupBox> 

<TextBlock MaxWidth="{Binding ElementName=layoutGrid, 
           Path=ActualWidth}" 
      HorizontalAlignment="Left" 
      VerticalAlignment="Top" 
      Text="{Binding ...}" 
      TextWrapping="Wrap" /> 
+0

嗨薇薇,谢谢你的提示。 IT无法在GroupBox或LayoutGrid上完成,因为它们是TextBlock的父元素,并且它们将设置其宽度与它们的小孩请求一样多(在我们的例子中,其中一个小孩是TextBlock)。但是,如果我们在layoutGrid外部移除GroupBox并将其放置在正下方,那么建议可以安全应用,然后它们的大小不会直接影响彼此,因此您的提示可以应用。 – Goran

+0

+1精彩小贴士@Viv。 – Sheridan

+0

几乎可以工作,但缩小尺寸并不会缩小'ActualWidth'。因此,只有升级是可能的。有没有解决方案? – bytecode77

0

如果你认为你的情况在逻辑上,那么你会明白,当然是TextBlock没有它Width属性设置不会被卷起时放在ScrollViewer里面。一个TextBlock只能通过包装其文本,如果它被告知什么时候开始包装......通过'when',我的意思是'在哪里'。需要说明的是,'在距离左侧150像素处开始包装文字内容'。

现在我们可以告诉它是这样做的:

<TextBlock Text="Some random long text string that is longer than 150 pixels long" 
    TextWrapping="Wrap" Width="150" /> 

或者这样:

<TextBlock Text="Some random long text string that is longer than 150 pixels long" 
    TextWrapping="Wrap" MaxWidth="150" /> 

或者这样:

<Grid Width="150"> 
    <TextBlock Text="Some random long text string that is longer than 150 pixels long" 
    TextWrapping="Wrap" /> 
</Grid> 

或者这样:

<Grid> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="150" /> 
    </Grid.ColumnDefinitions> 
    <TextBlock Grid.Column="0" Text="Some random long text string that is longer than 
     150 pixels long" TextWrapping="Wrap" /> 
</Grid> 

但是,如果您删除了Width限制,那么TextBlock将永远不会知道应该何时开始包装Text。通过将您的TextBlock置入ScrollViewer,您告诉它它拥有它可能需要的所有空间,因此,不设置Width限制,它将永远不会换行。

+0

你说我已经知道的一切。但正如我所说,我不能有固定宽度或TextBlock。但是,如果我采用Viv给出的方法,它会包装。我所要做的就是让layoutGrid不要成为TextBlock的父代。这样我们可以将TextBlock宽度设置为layoutGrid的宽度。 – Goran

0

我创建了一个控制包装IgnoreWidthControl为了这个目的:

public class IgnoreWidthControl : ContentControl 
{ 
    protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo) 
    { 
     base.OnRenderSizeChanged(sizeInfo); 
     if (sizeInfo.WidthChanged) 
      InvalidateMeasure(); 
    } 

    protected override Size MeasureOverride(Size constraint) 
    { 
     constraint.Width = ActualWidth; 
     Size size = new Size(); 
     UIElement child = GetFirstVisualChild(); 
     if (child != null) 
     { 
      child.Measure(constraint); 
      size.Height = child.DesiredSize.Height; 
     } 

     return size; 
    } 

    private UIElement GetFirstVisualChild() 
    { 
     if (this.VisualChildrenCount <= 0) 
      return null; 
     return this.GetVisualChild(0) as UIElement; 
    } 
} 

和示例使用:

<myc:IgnoreWidthControl> 
    <TextBlock Text="Very long text which has to be wrapped. Yeah, it must be wrapped." TextWrapping="Wrap" /> 
</myc:IgnoreWidthControl> 
相关问题