我認爲大量的代碼會推遲大多數人,所以我在開始時發佈解決方案,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();
}
}
我相信它需要一些變化,但現在它的工作原理。一旦我添加按鈕畫布的高度根據放置在底部的按鈕進行調整。
可能的重複[WPF:如何使畫布自動調整大小?](http://stackoverflow.com/questions/855334/wpf-how-to-make-canvas-auto-resize) – Sphinxxx 2014-12-14 14:43:22