Как вы динамически (с помощью кода) добавляете пользовательские элементы управления, созданные в XAML в WPF? - PullRequest
0 голосов
/ 18 февраля 2019

Я создал XAML «шаблонный» элемент управления с помощью Visual Stduio (и Blend), и он, конечно же, находится в XAML.Когда я ищу, как динамически добавлять элементы управления в ваш интерфейс, ответы всегда показывают, как создать элемент управления динамически, а затем добавить его.Мой вопрос: как добавить уже созданный элемент управления?

Я очень новичок в WPF и C # в целом.Возможно, я что-то упустил.Я задумался о том, что я могу создавать интерфейсы в Visual Studio с его графическим интерфейсом, а затем создавать внутренний код, но мне кажется, что есть кое-что еще, что я не понимаю.Я пытаюсь создать элемент управления, который по сути является «миниатюрой поиска» или, другими словами, цветной панелью с изображением и текстовым полем.Я установил изображение на ноль, а текст в поле - ноль, думая, что я могу изменить эти значения в коде.Я получаю список результатов поиска и пытаюсь добавить миниатюру элемента управления для каждого результата в том, что я предполагаю, является WrapPanel (я не уверен, что это именно то, что я хочу, но я верю, что это так).

Вот мой миниатюрный элемент управления с его XML Control

<UserControl x:Class="ChaCha.SearchThumbnail"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         xmlns:local="clr-namespace:ChaCha"
         mc:Ignorable="d" 
         d:DesignHeight="250 " d:DesignWidth="150"
                              TextElement.Foreground="{DynamicResource MaterialDesignBody}"
        Background="#FF3C3C3C"
    TextElement.FontWeight="Medium"
    TextElement.FontSize="14"
    FontFamily="pack://application:,,,/MaterialDesignThemes.Wpf;component/Resources/Roboto/#Roboto"
    >
<Grid x:Name="thumbnailGrid" Background="#FF004D40">
    <Image Source="{Binding thumbnailPath}" HorizontalAlignment="Left" Height="130" Margin="10,10,0,0" VerticalAlignment="Top" Width="130"/>
    <TextBlock x:Name="txt" HorizontalAlignment="Left" Margin="10,145,0,0" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="14" Height="95" Width="130" FontWeight="Normal" Text="{Binding thumbnailTxt}" TextAlignment="Center"/>

</Grid>

/// <summary>
/// Interaction logic for SearchThumbnail.xaml
/// </summary>
public partial class SearchThumbnail : UserControl
{

    public ImageSource ThumbnailPath { get; set; }
    public string ThumbnailTxt { get; set; }

    public SearchThumbnail()
    {
        InitializeComponent();
        DataContext = this;
    }
}

Я знаю, что этот код не соответствует формату MVVM, но япросто пробую быстрый и грязный способ обойти это быстро.Очевидно, что в будущем я поменяю его на более респектабельный метод, когда мне будет удобнее использовать WPF.

Внутри цикла for для результатов, которые корректно извлекаются:

                    // Getting a compatible Image object for the SearchThumbnail image Pane. Code from another stack overflow thread
                    var imgUrl = new Uri(thumbnail);
                    var imageData = new WebClient().DownloadData(imgUrl);

                    var bitmapImage = new BitmapImage { CacheOption = BitmapCacheOption.OnLoad };
                    bitmapImage.BeginInit();
                    bitmapImage.StreamSource = new MemoryStream(imageData);
                    bitmapImage.EndInit();

                    // OBVIOUSLY FAILED LAST ATTEMPT HERE.
                    var thumb = new SearchThumbnail()
                    {
                    ThumbnailTxt = title,
                    ThumbnailPath = bitmapImage
                    };
                    this.wrapPanel.Children.Add(thumb);

Я ожидалполный провал, но вместо этого я добавил элементы управления в основную панель с тем, что я предполагаю, это 0 полей.Изображение не отображается и текст не изменяется.

Result

1 Ответ

0 голосов
/ 18 февраля 2019

UserControl должен предоставлять свойства зависимости следующим образом:

public partial class SearchThumbnail : UserControl
{
    public SearchThumbnail()
    {
        InitializeComponent();
    }

    public static readonly DependencyProperty ImageProperty = DependencyProperty.Register(
        nameof(Image), typeof(ImageSource), typeof(SearchThumbnail));

    public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
        nameof(Text), typeof(string), typeof(SearchThumbnail));

    public ImageSource Image
    {
        get { return (ImageSource)GetValue(ImageProperty); }
        set { SetValue(ImageProperty, value); }
    }

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }
}

Обратите внимание, что вы не должны явно устанавливать DataContext UserControl в его конструкторе, в противном случае любое стандартное связывание свойств зависимости на основе DataContext не будет работать..

В его XAML вы привязываете к собственным свойствам UserControls, например, ReindingSource Bindings:

<UserControl ...>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Image Grid.Row="0"
            Source="{Binding Image, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
        <TextBlock Grid.Row="1"
            Text="{Binding Text, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
    </Grid>
</UserControl>

Как примечание, способ создания BitmapImage выглядит довольно странно.При условии, что у вас есть URL изображения, этого достаточно:

var bitmapImage = new BitmapImage(imgUrl);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...