好问题,当然有很多方法可以根据您的应用将执行的操作以及如何将每个控件的数据连接到您的应用/模型/其他内容来布局控件。
此答案侧重于布局,同时占用所有可用空间并允许复制每个容器中的内容。内容流畅地流动,直到窗口变得太小、太窄等等,这就是您需要决定您的应用程序将允许用户做什么的地方。在此代码达到生产质量之前还有很多工作要做,但它是熟悉 WPF 平台的一些 WPF 基础知识的一个很好的示例。
我为测试添加了一些边框、边距和背景颜色,这样您就可以看到哪个容器占用了多少空间。适合测试;在最终版本中可能会删除或更改为透明。
主窗口
XAML
<Grid x:Name="LayoutRoot">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel>
<TextBlock Text="WPF" FontSize="36" Margin="20" Foreground="Orange" HorizontalAlignment="Center"/>
</StackPanel>
<Grid Grid.Row="1" Margin="5">
<Border Background="LightGray" BorderBrush="Red" BorderThickness="1">
<UniformGrid Columns="4" Name="MainPanel"/>
</Border>
</Grid>
</Grid>
代码
public partial class MainWindow : Window
{
private static int _nextId = 0;
public static int NextId
{
get { return _nextId++; }
}
public MainWindow()
{
InitializeComponent();
DataContext = this;
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
// add non-multiple of 8 to see how layout works
for (var i=0; i<7; i++)
{
MainPanel.Children.Add(new EditPanelControl());
}
}
}
EditPanelControl(用户控件)
XAML
<Grid Margin="5">
<Border Background="LightYellow" BorderBrush="Green" BorderThickness="1">
<!-- Make this a viewbox if you want to show all items but have them shrink -->
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Disabled">
<StackPanel Name="MainPanel" VerticalAlignment="Center"/>
</ScrollViewer>
</Border>
</Grid>
代码
public partial class EditPanelControl : UserControl
{
public EditPanelControl()
{
InitializeComponent();
DataContext = this;
Loaded += EditPanelControl_Loaded;
}
private void EditPanelControl_Loaded(object sender, RoutedEventArgs e)
{
AddSuperTextControl();
}
private void AddSuperTextControl()
{
var stc = new SuperTextControl();
stc.SplitEvent += Stc_SplitEvent;
stc.DeleteEvent += Stc_DeleteEvent;
stc.SuperTextBox.Text = MainWindow.NextId.ToString();
MainPanel.Children.Add(stc);
}
private void Stc_DeleteEvent(object sender, EventArgs e)
{
// todo: don't allow delete if only 1 child
var stc = (SuperTextControl)sender;
MainPanel.Children.Remove(stc);
}
private void Stc_SplitEvent(object sender, EventArgs e)
{
var stc = (SuperTextControl)sender; // fyi
AddSuperTextControl();
}
}
SuperTextControl(用户控件)
XAML
<Grid Margin="5">
<Border Background="Wheat" BorderBrush="Blue" BorderThickness="1">
<StackPanel VerticalAlignment="Center" HorizontalAlignment="Stretch">
<TextBox Name="SuperTextBox" Margin="5"/>
<DockPanel LastChildFill="False" Margin="0,0,0,5">
<Button Content="Split" Click="SplitHandler" Margin="5,0" DockPanel.Dock="Left"/>
<Button Content="Delete" Click="DeleteHandler" Margin="5,0" DockPanel.Dock="Right"/>
</DockPanel>
</StackPanel>
</Border>
</Grid>
代码
public partial class SuperTextControl : UserControl
{
public event EventHandler SplitEvent;
public event EventHandler DeleteEvent;
public SuperTextControl()
{
InitializeComponent();
}
private void SplitHandler(object sender, RoutedEventArgs e)
{
var button = (Button)sender; // fyi
if (SplitEvent != null)
{
SplitEvent(this, new EventArgs());
}
}
private void DeleteHandler(object sender, RoutedEventArgs e)
{
var button = (Button)sender; // fyi
if (DeleteEvent != null)
{
DeleteEvent(this, new EventArgs());
}
}
}