繁体   English   中英

在WPF C#中动态添加UserControl

[英]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 / RowdefinitionColumn / ColumnDefinition

希望这可以帮助 :)

以下示例显示了如何使用DataTemplateWrapPanel创建多个已发布的图块。 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM