2010-06-11 90 views
2

我試圖做一些看起來應該是非常簡單的東西,但我看不出如何。我有一個非常簡單的佈局,一個帶有圖像旁邊的TextBox,類似於它可能在WinForms應用程序中使用ErrorProvider裝飾的方式。問題是,我希望圖像不超過它旁邊的文本框。如果我躺在出來這個樣子,說:如何將容器的高度限制爲特定內容元素的高度?

<Grid> 
    <Grid.RowDefinitions> 
    <RowDefinition Height="Auto"/> 
    </Grid.RowDefinitions> 
    <Grid.ColumnDefinitions> 
    <ColumnDefinition Width="Auto"/> 
    <ColumnDefinition Width="Auto"/> 
    </Grid.ColumnDefinitions> 
    <TextBox Grid.Row="0" Grid.Column="0" MinWidth="100"/> 
    <Image Grid.Row="0" Grid.Column="1" Source="error.png" /> 
</Grid> 

行將大小圖像的高度,如果圖像比文本框高。如果我使用DockPanel或StackPanel,也會發生這種情況。

天真的解決方案是將Height綁定到TextBoxActualHeight。我相信這是錯誤的。但是,什麼是對的?

編輯

這裏是什麼樣子我錯了一個例子:在這兩種佈局(這兩者都是水平StackPanel S)時,FontSize是唯一的變量:

Two examples showing unscaled icons

您可以看到第一個TextBox被限制在圖標的高度,結果在文本下面有不必要的底部填充。第二個圖標旁邊的圖標超出了TextBox的位置。

碰巧,我發現了一個完全不同的(並且更好)的方式來解決這個問題 - 本來我是通過在Window改變FontSize縮放我的佈局,但使用ScaleTransform是輕鬆許多,似乎完美地工作。但即便如此,我仍然覺得很難做到這一點。

回答

2

爲您的文本框命名,從圖像引用文本框如下。

<TextBox Name="myTextBox" 
     Grid.Row="0" Grid.Column="0" 
     MinWidth="100"/> 
<Image Grid.Row="0" 
     Grid.Column="1" 
     Source="error.png" 
     Height="{Binding ActualHeight, ElementName=myTextBox}"/> 
+1

好吧,就像我說的,這是一個天真的解決方案,我懷疑這是錯誤的 - 不是因爲它不會工作,而是因爲綁定到ActualHeight和ActualWidth會導致真正明顯的性能問題。 – 2010-06-12 17:28:25

+0

我使用這個想法保持圖像的高度與組合框中的高度文本相同,並取得了很好的成功。 – Zamboni 2010-06-12 23:23:59

1

你想要一個佈局算法來測量高度約束等於特定高度的其他元素。儘管現有的一些面板實現會根據前面使用的大小減少剩餘元素的可用空間,但它們都不會按照您想要的方式設置約束。如果您想要在單個佈局過程中描述的行爲,則需要編寫自己的佈局算法。

例如,您可以通過重寫的StackPanel的行爲,這樣的親近:

public class SizeToFirstChildStackPanel 
    : StackPanel 
{ 
    protected override Size MeasureOverride(Size constraint) 
    { 
     if (Children.Count > 0) 
     { 
      var firstChild = Children[0]; 
      firstChild.Measure(constraint); 
      if (Orientation == Orientation.Horizontal) 
      { 
       constraint = new Size(
        constraint.Width, 
        Math.Min(firstChild.DesiredSize.Height, constraint.Height)); 
      } 
      else 
      { 
       constraint = new Size(
        Math.Min(firstChild.DesiredSize.Width, constraint.Width), 
        constraint.Height); 
      } 
     } 
     return base.MeasureOverride(constraint); 
    } 
} 

這將StackPanel中的所有兒童的身高限制的第一個期望的高度(或寬度,如果面板垂直取向)。

它仍然不理想,因爲第一個孩子將被基類MeasureOverride第二次測量,第二個測量將會有一個約束。這是額外的工作,如果第一個孩子想要變大,會造成奇怪的行爲。

要做到這一點,您需要自己實施整個MeasureOverride方法。我不打算在這裏這樣做,因爲它會涉及很多與問題無關的代碼,這取決於您希望佈局如何工作。重要的一點是先測量特定元素,並在其他人上調用Measure時使用其DesiredSize來確定availableSize。