簡體   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