Stack Overflow на русском Asked by axmed2004 on August 30, 2021
список может состоять из элементов 2 типов: текст и ссылка. ObservableCollection может содержать соот-но разные объекты с type="url"
или type="text"
class Item
{
string type;
string title;
string titleshort;
string time;
}
collection.Add(new Item{type="url",title="http://url",time=datetime});
collection.Add(new Item{type="text",title="text text text ....", titleshort="text ..." ,time=datetime});
<ItemsControl>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border>
<TextBlock Tag="{Binding title}"
Cursor="Hand"
TextWrapping="Wrap">
<Run Text="{Binding titleshort}" PreviewMouseDown="openTextFromHistory"/>
<Run Text="{Binding timeblock}"/>
</TextBlock>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
В случае url шаблон должен быть таким:
<Border>
<TextBlock>
<Hyperlink NavigateUri="{Binding title}">
<Run Text="{Binding title}"/>
</Hyperlink>
<Run Text="{Binding time}"/>
</TextBlock>
</Border>
В случае text таким:
<Border>
<TextBlock Tag="title" PreviewMouseLeftButtonDown="somemethod">
<Run Text="{Binding titleshort}"/>
<Run Text="{Binding time}"/>
</TextBlock>
</Border>
как вставлять нужный шаблон в зависимости от type
?
UPD
Пространства имен в MainWindow.xaml:
x:Class="RemoteControl.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:RemoteControl"
mc:Ignorable="d"
Обычно это делается при помощи разных классов, наследуемые от одного "предка".
Возьмем к примеру два ваших типа text
и url
:
И так, думаем для начала что у них общего, а общего у них простой текст, либо он http://site.ru
, либо он Это обычный текст
, а значит мы можем сделать интерфейс (если не нужна общая логика), либо класс, от них мы будем наследоваться.
public interface ITextProperty
{
public string Text { get; set; }
}
Все, нам этого достаточно для дальнейшей работы.
Дальше нам нужны классы, которые будут содержать в себе все необходимое для текста или ссылки:
class TextProperty : ITextProperty
{
public TextProperty(string text, double fontSize)
=> (Text, FontSize) = (text, fontSize);
public string Text { get; set; }
public double FontSize { get; set; }
}
class UrlProperty : ITextProperty
{
public UrlProperty(string url)
=> (Text, OpenCommand) = (url, new RelayCommand(Open));
public string Text { get; set; }
public ICommand OpenCommand { get; }
public void Open() => Process.Start(Text);
}
Как видите это два простейших класса, где в тексте мы можем задать дополнительно размер, у ссылки имеется простая команда открытия этой самой ссылки.
Теперь сделаем текстовые данные. Тут нам нужна коллекция, содержащая в себе именно тот интерфейс/класс, от которого мы наследуемся, в нашем случае это ITextProperty
.
public ObservableCollection<ITextProperty> Items { get; }
Добавим пару тестовых данных:
Items = new ObservableCollection<ITextProperty>
{
new TextProperty("Привет мир!", 17),
new UrlProperty("http://google.ru"),
new TextProperty("Привет мир!", 8)
};
Осталось дело за малым - UI, нам надо заставить XAML понимать это и отдавать нужный нам дизайн под каждый объект. Для таких целей отлично подойдет DataTemplate
, который позволяет задать напрямую нужный тип, к которому будет применен указанный стиль. Обычно он задается в ресурсах, я сделаю это в ресурсах Grid
, в котором расположено отображение коллекции. Получаем в итоге такое:
<Grid>
<Grid.Resources>
<DataTemplate DataType="{x:Type local:TextProperty}">
<TextBlock Text="{Binding Text}" FontSize="{Binding FontSize}" Margin="5"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:UrlProperty}">
<Button Background="Transparent"
BorderThickness="0 0 0 1"
Content="{Binding Text}"
Command="{Binding OpenCommand}"
Cursor="Hand"/>
</DataTemplate>
</Grid.Resources>
<ItemsControl ItemsSource="{Binding Items}" HorizontalAlignment="Center"/>
</Grid>
Запускаем и любуемся результатом
Программа успешно отобразила два текста с разным размером и одну кнопку, которая кликабельна и открывает через браузер указанную ссылку.
Это самой оптимальный и удобный (как по мне) вариант, как такое можно сделать. Конечно, он не единственный и можно взять прямиком ваш код, где один объект, отличие которого в одном свойстве, делается это через триггеры, например:
<DataTrigger Binding="{Binding Type}" Value="Text">
<!-- Дизайн -->
</DataTrigger>
В общем, удачи в изучении.
Кстати, если вам надо в тексте выделить все ссылки, то это делается вовсе другими методами.
Correct answer by EvgeniyZ on August 30, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP