[英]Add UserControl dynamically in WPF C#
我的WPF应用程序中有一个页面,该页面应该显示一些“平铺”,如我之前指定的那样。 磁贴看起来像这样:
当然,可以通过手动克隆图块来实现,但是我想避免这种情况(以更多编程方式实现)。 因此,我应该只保留一个克隆,而不是创建6个克隆,然后根据需要添加其余的克隆。 我该怎么做? 我想我应该像这样创建自己的UserControl:
<Grid HorizontalAlignment="Left" Height="199" VerticalAlignment="Top" Width="207" Background="Black">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="0*"/>
</Grid.RowDefinitions>
<Image x:Name="image1" HorizontalAlignment="Left" Height="175" VerticalAlignment="Top" Width="207" Stretch="UniformToFill"/>
<Grid HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="112" Background="#FFC78D10">
<TextBox IsReadOnly = "True" x:Name="CategoryOfEvent" Height="30" TextWrapping="Wrap" Text="Category" Width="112" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="White" FontSize="18" SelectionBrush="{x:Null}" HorizontalAlignment="Left" VerticalAlignment="Top" >
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer Name="PART_ContentHost"/>
</ControlTemplate>
</TextBox.Template>
</TextBox>
</Grid>
<TextBox IsReadOnly = "True" x:Name="HourOfEvent" HorizontalAlignment="Left" Height="28" Margin="0,42,0,0" TextWrapping="Wrap" Text="Hour" VerticalAlignment="Top" Width="148" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="#FFE2E2E2" FontSize="22" SelectionBrush="{x:Null}" FontWeight="Bold" TextChanged="HourOfEvent_TextChanged">
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer Name="PART_ContentHost"/>
</ControlTemplate>
</TextBox.Template>
</TextBox>
<TextBox IsReadOnly = "True" x:Name="TitleOfEvent" HorizontalAlignment="Left" Height="88" Margin="0,82,0,0" TextWrapping="Wrap" Text="Title" VerticalAlignment="Top" Width="207" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="White" FontSize="20" SelectionBrush="{x:Null}" FontWeight="Bold">
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer Name="PART_ContentHost"/>
</ControlTemplate>
</TextBox.Template>
</TextBox>
<TextBox IsReadOnly = "True" x:Name="PlaceOfEvent" HorizontalAlignment="Left" Height="24" Margin="0,175,0,0" TextWrapping="Wrap" Text="Where" VerticalAlignment="Top" Width="207" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="White" FontSize="14" SelectionBrush="{x:Null}">
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer Name="PART_ContentHost"/>
</ControlTemplate>
</TextBox.Template>
</TextBox>
</Grid>
并将它们添加到我的页面中。 我还要提及的是,在每个图块中都有4个文本框,这些文本框显示了从Json解析的一些数据,因此也许可以执行一些自动绑定吗?
就是这么简单。首先,您可以做的是创建一个UserControl
其中包含所有控件,例如TextBlock
和其他控件。然后,确定要用于保存UserControl
的容器控件类型。让我们假设它是一个您可以为每个用户控件指定/设置网格的列/行。
private void addControl()
{
UserControl1 MyCon = new UserControl1;
MyGrid.Children.Add(MyCon);
Grid.SetRow(MyCon , 1); ////replace 1 with required row count
}
您可以在设计时创建网格行,也可以在后面的代码中创建网格行:
MyGrid.RowDefinitions.Add(new RowDefinition);
如果你想使用的列,而不是,只是采用相同的代码,但改变Row
/ Rowdefinition
与Column
/ ColumnDefinition
希望这可以帮助 :)
以下示例显示了如何使用DataTemplate
和WrapPanel
创建多个已发布的图块。 DataTemplate指定如何显示对象(在本例中为TileItem
)。 您可以创建多个TileItem
,然后将它们添加到集合中,以使它们全部可视化。
假设您的UI位于MainWindow中,则可以创建一个包含三个项目的集合。
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
TileItemCollection = new ObservableCollection<TileItem>(new []
{
new TileItem(){Category = "Alpha", Hour = "10", Title = "Hello World", Where = "Office"},
new TileItem(){Category = "Beta", Hour = "15", Title = "Test", Where = "Home"},
new TileItem(){Category = "Gamma", Hour = "44", Title = "My Title", Where = "Work"},
});
DataContext = this;
}
public ObservableCollection<TileItem> TileItemCollection { get; }
}
您可以从JSON加载项目,并为JSON文档中的每个项目创建一个TileItem
。 TileItems
的类可以在下面找到。
public class TileItem : INotifyPropertyChanged
{
private string _hour;
private string _title;
private string _where;
private string _category;
public string Category
{
get => _category;
set
{
if (value == _category) return;
_category = value;
OnPropertyChanged();
}
}
public string Hour
{
get => _hour;
set
{
if (value == _hour) return;
_hour = value;
OnPropertyChanged();
}
}
public string Title
{
get => _title;
set
{
if (value == _title) return;
_title = value;
OnPropertyChanged();
}
}
public string Where
{
get => _where;
set
{
if (value == _where) return;
_where = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
请注意,为了将数据更改传播到UI,在代码中更新属性时应在UI中更新的所有属性都需要引发属性更改事件。 在此示例中,所有属性默认情况下都执行此操作。
然后,您可以更新XAML以绑定到集合。 ItemsControl
充当图块的容器。 如果向下滚动,您可能会注意到WrapPanel
的使用,当您调整控件的大小时, WrapPanel
会导致项目包装效果。
<ItemsControl ItemsSource="{Binding TileItemCollection}" Margin="20">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:TileItem}" >
<Grid HorizontalAlignment="Left" Height="199" VerticalAlignment="Top" Width="207" Background="Black">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition Height="0*"/>
</Grid.RowDefinitions>
<Image x:Name="image1" HorizontalAlignment="Left" Height="175" VerticalAlignment="Top" Width="207" Stretch="UniformToFill"/>
<Grid HorizontalAlignment="Left" Height="30" VerticalAlignment="Top" Width="112" Background="#FFC78D10">
<TextBox IsReadOnly="True" Height="30" TextWrapping="Wrap" Text="{Binding Path=Category}" Width="112" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="White" FontSize="18" SelectionBrush="{x:Null}" HorizontalAlignment="Left" VerticalAlignment="Top" >
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer Name="PART_ContentHost"/>
</ControlTemplate>
</TextBox.Template>
</TextBox>
</Grid>
<TextBox IsReadOnly="True" HorizontalAlignment="Left" Height="28" Margin="0,42,0,0" TextWrapping="Wrap" Text="{Binding Path=Hour}" VerticalAlignment="Top" Width="148" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="#FFE2E2E2" FontSize="22" SelectionBrush="{x:Null}" FontWeight="Bold">
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer Name="PART_ContentHost"/>
</ControlTemplate>
</TextBox.Template>
</TextBox>
<TextBox IsReadOnly="True" HorizontalAlignment="Left" Height="88" Margin="0,82,0,0" TextWrapping="Wrap" Text="{Binding Path=Title}" VerticalAlignment="Top" Width="207" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="White" FontSize="20" SelectionBrush="{x:Null}" FontWeight="Bold">
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer Name="PART_ContentHost"/>
</ControlTemplate>
</TextBox.Template>
</TextBox>
<TextBox IsReadOnly="True" x:Name="PlaceOfEvent" HorizontalAlignment="Left" Height="24" Margin="0,175,0,0" TextWrapping="Wrap" Text="{Binding Path=Where}" VerticalAlignment="Top" Width="207" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="White" FontSize="14" SelectionBrush="{x:Null}">
<TextBox.Template>
<ControlTemplate TargetType="{x:Type TextBox}">
<ScrollViewer Name="PART_ContentHost"/>
</ControlTemplate>
</TextBox.Template>
</TextBox>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.Template>
<ControlTemplate>
<ScrollViewer>
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</ItemsControl.Template>
</ItemsControl>
每个图块都绑定到一个TileItem
,这意味着指向例如Category的Bindings指向TileItem的Category。
为了提高可重用性,可以将代码移到其自己的usercontrol中,并可以选择添加DependencyProperty
以获得更好的控制。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.