2014-12-13 39 views
1

調整畫布我寫如何根據孩子<wpf>

<TabItem Header="Map"> 
    <Grid Background="#FFE5E5E5" Margin="0,0,0,0"> 
     <ScrollViewer x:Name="mapScroll" HorizontalAlignment="Left" Height="248" Margin="10,10,0,0" VerticalAlignment="Top" Width="467" HorizontalScrollBarVisibility="Auto"/> 
    </Grid> 
    </TabItem> 

,並添加代碼

Canvas ca=new Canvas(); 
mapScroll.Content=ca; 

,並添加

Button btnTest1 = new Button(); 
    btnTest1.Width = 100; 
    btnTest1.Height = 150; 
    Canvas.SetLeft(btnTest1, 200); 
    Canvas.SetTop(btnTest1, 200); 
ca.Children.Add(btnTest1); 

按鈕定位於畫布的邊界區域。 按鈕的一側不可見,並且滾動條未被激活。 我想調整畫布大小以包含完整按鈕,因此應該激活滾動條... ScollViewer尺寸相同。

我如何調整畫布的大小,所以滾動條必須激活。

+0

可能的重複[WPF:如何使畫布自動調整大小?](http://stackoverflow.com/questions/855334/wpf-how-to-make-canvas-auto-resize) – Sphinxxx 2014-12-14 14:43:22

回答

0

我認爲大量的代碼會推遲大多數人,所以我在開始時發佈解決方案,here。 我的想法是使Canvas的高度依賴於Canvas.Children.Count。每次收集變化時,這將改變Canvas的高度。但不幸的是,Children.Count不是依賴屬性,因此它不反映任何更改。我用ChildrenCount屬性實現了自定義畫布,它讓我們知道變化。另一個問題是,Canvas沒有提供任何事件給它的子項添加項目,所以我被迫從基類中覆蓋OnVisualChildrenChanged事件。我相信你對這段代碼的理解。

public class CustomCanvas : Canvas, INotifyPropertyChanged 
{ 
    private int childrenCount; 

    public int ChildrenCount 
    { 
     get { return childrenCount; } 
     set 
     { 
      childrenCount = value; 
      OnPropertyChanged(); 
     } 
    } 

    protected override void OnVisualChildrenChanged(DependencyObject visualAdded, DependencyObject visualRemoved) 
    { 
     if (visualAdded == null) 
      --ChildrenCount; 
     else 
      ++ChildrenCount; 
     base.OnVisualChildrenChanged(visualAdded, visualRemoved); 
    } 

    public void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     if (PropertyChanged != null) 
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
} 

XAML:

<StackPanel> 
    <StackPanel.Resources> 
     <local:ChildrenCountToHeightConverter x:Key="ChildrenCountToHeightConverter"/> 
    </StackPanel.Resources> 
    <ScrollViewer HorizontalAlignment="Left" Height="248" Margin="10,10,0,0" VerticalAlignment="Top" Width="467" 
        HorizontalScrollBarVisibility="Auto" 
      VerticalScrollBarVisibility="Auto"> 
     <local:CustomCanvas x:Name="CustomCanvas" MaxHeight="1555"> 
      <local:CustomCanvas.Height> 
       <MultiBinding Converter="{StaticResource ChildrenCountToHeightConverter}"> 
        <Binding RelativeSource="{RelativeSource Self}" Path="(local:CustomCanvas.ChildrenCount)"/> 
        <Binding RelativeSource="{RelativeSource Self}" Path="(local:CustomCanvas.Children)"/> 
       </MultiBinding> 
      </local:CustomCanvas.Height> 
     </local:CustomCanvas> 
    </ScrollViewer> 
    <Button Content="dodaj" Click="ButtonBase_OnClick"/> 
</StackPanel> 


private void ButtonBase_OnClick(object sender, RoutedEventArgs e) 
    { 
     Button btnTest1 = new Button(); 
     btnTest1.Width = 100; 
     btnTest1.Height = 150; 
     Canvas.SetLeft(btnTest1, 200); 
     Canvas.SetTop(btnTest1, 200); 
     CustomCanvas.Children.Add(btnTest1); 
    } 


public class ChildrenCountToHeightConverter : IMultiValueConverter 
{ 
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     var childrenNumber = System.Convert.ToInt32(values[0].ToString()); 
     if (childrenNumber == 0) 
      return 0; 
     var children = (UIElementCollection)values[1]; 
     var y = children.OfType<Button>().Max(x => Canvas.GetTop(x)); 
     return y + children.OfType<Button>().First(x => Canvas.GetTop(x) == y).Height + 50; 
    } 

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

我相信它需要一些變化,但現在它的工作原理。一旦我添加按鈕畫布的高度根據放置在底部的按鈕進行調整。

+0

謝謝。這段代碼工作得很好。但是我必須添加Image和TextBlock,所以我更改'children.OfType

+0

而且我想讓它適應不僅垂直而且水平對齊。 – Lightstar 2014-12-15 15:38:45

+0

如果你想要不同類型的對象,只需添加他們的基本類如FrameworkElement而不是Image或Button。如果你想要寬度,你需要添加與高度相同的綁定,但添加另一個轉換器,您將在其中尋找Canvas.GetLeft(obj)。如果它有用,請將其標記爲answear。 – Maximus 2014-12-15 18:47:10