WPF список с разными цветами

1

У меня проблема со списком, который должен учитывать разные цвета в его Элементах.

    <ListBox i:Name="listBox1" ItemsSource="{Binding MyItems_listbox1}" 
     IsSynchronizedWithCurrentItem="True">

Теперь я хочу добавить элемент в список, если строка написана разными цветами, например:

listBox1.Items.Add("hallo my name");

Я хочу, чтобы в "список" и отобразилось "hallo" (синее) "мое" (красное) "имя" (зеленое). Есть ли какой-то возможный способ реализовать это?

  • 1
    Есть несколько способов добиться того же. перед этим вам может понадобиться определить правила раскрашивания. Поэтому, если бы вы могли определить их, мы можем попытаться показать вам путь.
  • 0
    Вы просто хотите, чтобы первое слово синее, второе слово красное, третье слово зеленое или конкретные слова, которые вы описали?
Показать ещё 1 комментарий
Теги:
wpf
listbox

2 ответа

1
Лучший ответ

Чтобы выделить какое-то слово, обычно мы можем думать о управлении RichTextBox. Однако это не легкий контроль веса. Ему повезло, что WPF поддерживает множество элементов управления (особенно связанных с Document), что позволяет нам отображать богатый текст. Для облегченного решения вы должны просто использовать TextBlock представляющий контент для каждого ListViewItem но мы можем использовать элементы Run внутри каждого TextBlock чтобы выделить слова. Во-первых, нам нужно использовать DataTemplate для установки ItemTemplate для каждого ListViewItem. Мы должны использовать Binding для привязки содержимого строки (каждого элемента) к TextBlock внутри DataTemplate. Использование Binding позволяет нам вводить какой-то пользовательский код в Converter. Вот код детали:

Код позади:

//The main window class
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        //Init the Keywords first
        Keywords.Add("hallo", Brushes.Blue);
        Keywords.Add("my", Brushes.Red);
        Keywords.Add("name", Brushes.Green);

        //Add some items to the ListView
        lv.Items.Add("hallo my name");
        lv.Items.Add("hello my name");
        lv.Items.Add("goodbye your name");            
    }
    //This dictionary used to hold your keywords corresponding to their Brush
    public static Dictionary<string, Brush> Keywords = new Dictionary<string,Brush>();
}

//The converter class
public class InlinesConverter : IValueConverter
{
    object IValueConverter.Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        var content = Convert.ToString(value);
        var dict = MainWindow.Keywords;
        var outString = "<TextBlock xmlns=\"http://schemas.microsoft.com/winfx/2006/xaml/presentation\"  xml:space=\"preserve\">";
        foreach(var word in content.Split(' ')){
            var converted = word;
            Brush fg;
            if (dict.TryGetValue(word, out fg)) {
                var run = new Run(word);
                run.Foreground = fg;
                converted = System.Windows.Markup.XamlWriter.Save(run);
            }
            outString += converted + " ";
        }
        outString += "</TextBlock>";            
        return System.Windows.Markup.XamlReader.Parse(outString);            
    }

    object IValueConverter.ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

XAML:

<Window x:Class="WpfApplication.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="SO3" Height="300" Width="300"
    xmlns:local="clr-namespace:WpfApplication"
    >
  <Window.Resources>
    <local:InlinesConverter x:Key="inlinesConverter"/>
  </Window.Resources>
  <Grid>
    <ListView Name="lv">            
        <ListView.ItemTemplate>
            <DataTemplate>                    
                <ContentControl FontSize="20">
                   <Binding Converter="{StaticResource inlinesConverter}"/>
                </ContentControl>
            </DataTemplate>
        </ListView.ItemTemplate>            
    </ListView>
  </Grid>
</Window>

Обратите внимание на пространство имен здесь, в этой демонстрации я использовал пространство имен по умолчанию WpfApplication. Если у вас другое, вы должны отредактировать его внутри кода XAML. Также обратите внимание, что ItemTemplate игнорируется, если вы добавляете элементы прямо в код XAML. Мы должны использовать код, расположенный либо через Items.Add либо привязку данных (с помощью ItemsSource).

Изображение 174551

  • 1
    Благодарю. Это именно то, что я искал.
1

Вероятным способом добиться этого может быть использование ListBox DataTemplate где вы будете отправлять строку в виде массива, а затем внутри DataTemplate вы можете иметь другой TextBlock для всех частей строки

<TextBlock Text="hallo " Foreground="Blue" />
<TextBlock Text="my" Foreground="Red" />
<TextBlock Text=" name" Foreground="Green" />

Ещё вопросы

Сообщество Overcoder
Наверх
Меню