locked
Replace Characters with Image in TextBlock RRS feed

  • Question

  • Hi All Am Developing Simple Application which has ListBox 

    List Box has Datatemplate which contains TextBlock

    TextBox has binding from my Viewmodel

    when i have ":)" or ";(" i need to replace this text with emoji

    so far i have achieved till Below  Line of code.

    I need to replace some characters with image in textblock

      <TextBlock HorizontalAlignment="Left" 
                                                   Text="{Binding MessageText}"                                                                                           
                                                  >
                                                        <Run>:)
                                                        </Run>
                                            <InlineUIContainer>
                                                <Image Source="http://sstatic.net/stackoverflow/img/apple-touch-icon.png" Height="20"></Image>
                                            </InlineUIContainer>
                                            <Run>:(</Run>
                                            <Run>:)</Run>
                                            <Run>:)</Run>
                                            
                                        </TextBlock> 

    Any Suggestion would be of great help.

    Thanks


    Arjun

    Thursday, March 10, 2016 7:29 PM

Answers

  • You cannot both bind the Text property and add inlines to the TextBlock.

    But you could replace the TextBlock with a ContentControl in the XAML markup and use a converter that creates a TextBlock with inlines. Please refer to the following sample code:

            <DataTemplate xmlns:local="clr-namespace:WpfApplication5">
                <DataTemplate.Resources>
                    <local:TextConverter x:Key="TextConverter"/>
                </DataTemplate.Resources>
                <ContentControl Content="{Binding MessageText, Converter={StaticResource TextConverter}}">
                </ContentControl>
            </DataTemplate>

    namespace WpfApplication5
    {
        public class TextConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                TextBlock textBlock = new TextBlock();
                string text = value as string;
                for(int i = 0; i < text.Length; ++i)
                {
                    if(text[i] == ':' && i < (text.Length -1 ) && (text[i+1] == ')' || text[i+1] == '('))
                    {
                        Image image = new Image() { Width = 20, Height = 20 };
                        BitmapImage source = new BitmapImage();
                        source.BeginInit();
                        if (text[i + 1] == '(')
                            source.UriSource = new Uri("http://sstatic.net/stackoverflow/img/apple-touch-icon.png", UriKind.Absolute);
                        else
                            source.UriSource = new Uri("https://assets.onestore.ms/cdnfiles/onestorerolling-1602-26000/shell/v3/images/logo/microsoft.png", UriKind.Absolute);
                        source.EndInit();
                        image.Source = source;
    
                        InlineUIContainer container = new InlineUIContainer(image);
                        
                        textBlock.Inlines.Add(container);
                        i++;
                    }
                    else
                    {
                        textBlock.Inlines.Add(new Run(text[i].ToString()));
                    }
                }
    
    
                return textBlock;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotSupportedException();
            }
        }
    }
    

    public string MessageText {
                get { return "abc:)def:("; }
            }

    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Thursday, March 10, 2016 8:59 PM

All replies

  • List Box has Datatemplate which contains TextBlock

    That doesn't seem to match your markup.

    I would define 2 viewmodel types.

    One being a textblockvm with a text property.

    The other an imagevm with an imagesource property.

    Then 2 datatemplates which use datatype to match the corresponding viewmodel.

    Thus when the view gets a textblockvm it produces a textblock and when it gets and imagevm it produces an image.

    Then put a horizontal ListView or itemscontrol in you listboxitem template.

    Use regex to split your strings up into smiles and regular string in a similar ( but not exactly the same ) way to this sample:

    https://gallery.technet.microsoft.com/WPF-Highlight-Matching-71ad5a04

    That highlights matching words rather than substituting images but it's doing the stackpanel in each row thing.

                <ListBox.ItemTemplate>
                    <DataTemplate>
                        <ListView ItemsSource="{Binding .}" >
                            <ListView.ItemContainerStyle>
                                <Style TargetType="{x:Type ListViewItem}">
                                    <Setter Property="Template">
                                        <Setter.Value>
                                            <ControlTemplate TargetType="{x:Type ListViewItem}">
                                                <TextBlock Text="{Binding Text}">
                                                    <TextBlock.Style>
                                                        <Style TargetType="TextBlock">
                                                            <Style.Triggers>
                                                                <DataTrigger Binding="{Binding IsMatch}" Value="True">
                                                                    <Setter Property="Background" Value="Yellow" />
                                                                </DataTrigger>
                                                            </Style.Triggers>
                                                        </Style>
                                                    </TextBlock.Style>
                                                </TextBlock>
                                            </ControlTemplate>
                                        </Setter.Value>
                                    </Setter>
                                </Style>
                            </ListView.ItemContainerStyle>
                            <ListView.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal"></StackPanel>
                                </ItemsPanelTemplate>
                            </ListView.ItemsPanel>
                        </ListView>
                    </DataTemplate>
                </ListBox.ItemTemplate>
    That's stacking items horizontally, in each row of the listbox.


    Hope that helps.

    Technet articles: WPF: Layout Lab; All my Technet Articles

    Thursday, March 10, 2016 7:57 PM
  • You cannot both bind the Text property and add inlines to the TextBlock.

    But you could replace the TextBlock with a ContentControl in the XAML markup and use a converter that creates a TextBlock with inlines. Please refer to the following sample code:

            <DataTemplate xmlns:local="clr-namespace:WpfApplication5">
                <DataTemplate.Resources>
                    <local:TextConverter x:Key="TextConverter"/>
                </DataTemplate.Resources>
                <ContentControl Content="{Binding MessageText, Converter={StaticResource TextConverter}}">
                </ContentControl>
            </DataTemplate>

    namespace WpfApplication5
    {
        public class TextConverter : IValueConverter
        {
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                TextBlock textBlock = new TextBlock();
                string text = value as string;
                for(int i = 0; i < text.Length; ++i)
                {
                    if(text[i] == ':' && i < (text.Length -1 ) && (text[i+1] == ')' || text[i+1] == '('))
                    {
                        Image image = new Image() { Width = 20, Height = 20 };
                        BitmapImage source = new BitmapImage();
                        source.BeginInit();
                        if (text[i + 1] == '(')
                            source.UriSource = new Uri("http://sstatic.net/stackoverflow/img/apple-touch-icon.png", UriKind.Absolute);
                        else
                            source.UriSource = new Uri("https://assets.onestore.ms/cdnfiles/onestorerolling-1602-26000/shell/v3/images/logo/microsoft.png", UriKind.Absolute);
                        source.EndInit();
                        image.Source = source;
    
                        InlineUIContainer container = new InlineUIContainer(image);
                        
                        textBlock.Inlines.Add(container);
                        i++;
                    }
                    else
                    {
                        textBlock.Inlines.Add(new Run(text[i].ToString()));
                    }
                }
    
    
                return textBlock;
            }
    
            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotSupportedException();
            }
        }
    }
    

    public string MessageText {
                get { return "abc:)def:("; }
            }

    Hope that helps.

    Please remember to close your threads by marking helpful posts as answer and then start a new thread if you have a new question. Please don't ask several questions in the same thread.

    Thursday, March 10, 2016 8:59 PM