Bind textblock to two properties
Asked Answered
M

7

13

I have a Textblock that is bound to a property in the ItemsSource collection. I'd like to display two properties from that class in the same textblock, but it seems I can only perform one binding at a time. I currently have this:

Text="{Binding Title}"

but I want I want to append another property, so in theory it would be:

Text="{Binding Title - Author}" 

with the output looking like "Shakespeare - Romeo and Juliet". I've tried adding a comma, another binding and other things, but they all result in an exception being thrown (e.g. Unknown attribute Text on element TextBlock).

Both properties comes from the same class, so I won't need to have two data sources.

Mihalco answered 15/6, 2011 at 17:20 Comment(3)
Are you using the MVVM pattern? If so, just create another property on your view model that returns the string in the way you wish.Cornejo
If you were using a ViewModel from the MVVM pattern, you could just add a property to meet your needs. By the way, why not use 2-3 texblocks?Calvin
Not using MVVM. I tried using multiple textblocks, but I needed to position the text next to each other and some text was longer than others, so it would be tricky to lines them all up perfectly.Mihalco
L
8

Unfortunately silverlight is missing a few pieces that WPF has that can handle this. I would probably go the route of using a value converter that you can pass the class that contains the Title and Author to format the text.

Here's the code:

public class TitleAuthorConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value is Book)) throw new NotSupportedException();
        Book b = value as Book;
        return b.Title + " - " + b.Author;
    }

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

public class Book
{
    public string Title { get; set; }
    public string Author { get; set; }
}

And some XAML:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.Resources>
        <local:Book Title="Some Book" Author="Some Author" x:Key="MyBook"/>
        <local:TitleAuthorConverter x:Key="Converter"/>
    </Grid.Resources>
    <TextBlock DataContext="{StaticResource MyBook}" Text="{Binding Converter={StaticResource Converter}}"/>
</Grid>

The downside to this way is that you won't get the text to update if the properties change (ie you implement INotifyPropertyChanged) since the field is bound to the class.

As suggested in the comments on the question, you could also create a third property that combines them. This would get around having to use multibindings or value converters.

Lobar answered 15/6, 2011 at 17:33 Comment(1)
Thanks. I'll use a Value Converter as the properties for this won't change during runtime.Mihalco
T
18

Use this one.. It will work Perfectly.

<TextBlock>
    <Run Text="{Binding Title}"></Run>
    <Run Text=":"></Run>
    <Run Text="{Binding Author}"></Run> 
</TextBlock>

the output will be like this,

OOPS:Balagurusamy

Trover answered 2/11, 2012 at 10:35 Comment(0)
L
8

Unfortunately silverlight is missing a few pieces that WPF has that can handle this. I would probably go the route of using a value converter that you can pass the class that contains the Title and Author to format the text.

Here's the code:

public class TitleAuthorConverter : IValueConverter
{

    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (!(value is Book)) throw new NotSupportedException();
        Book b = value as Book;
        return b.Title + " - " + b.Author;
    }

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

public class Book
{
    public string Title { get; set; }
    public string Author { get; set; }
}

And some XAML:

<Grid x:Name="LayoutRoot" Background="White">
    <Grid.Resources>
        <local:Book Title="Some Book" Author="Some Author" x:Key="MyBook"/>
        <local:TitleAuthorConverter x:Key="Converter"/>
    </Grid.Resources>
    <TextBlock DataContext="{StaticResource MyBook}" Text="{Binding Converter={StaticResource Converter}}"/>
</Grid>

The downside to this way is that you won't get the text to update if the properties change (ie you implement INotifyPropertyChanged) since the field is bound to the class.

As suggested in the comments on the question, you could also create a third property that combines them. This would get around having to use multibindings or value converters.

Lobar answered 15/6, 2011 at 17:33 Comment(1)
Thanks. I'll use a Value Converter as the properties for this won't change during runtime.Mihalco
R
6

Sounds like you need a MultiBinding.

<TextBlock.Text>
    <MultiBinding StringFormat="{}{0} - {1}">
        <Binding Path="Title" />
        <Binding Path="Author" />
    </MultiBinding>
</TextBlock.Text>
Rash answered 15/6, 2011 at 17:22 Comment(0)
P
1

You can use special extension from CodeProject

Example

<TextBlock>
<TextBlock.Text>
    <MultiBinding StringFormat="{}{0} {1}" >
        <Binding Path="FirstName" />
        <Binding Path="LastName" />
    </MultiBinding>
</TextBlock.Text>
</TextBlock>
Packing answered 5/2, 2016 at 10:33 Comment(0)
R
0

I found a MultiBinding sample project for Silverlight on the net, there are a number of them I believe, just Google it. If you can't find one let me know I'll send you the one we're using. Does anyone know if multi-binding is coming to SL 5? You can use a 3rd property as well, just remember to fire it's PropertyChanged event when ever either of it's constituents changes then binding will be fine.

Ruttish answered 17/6, 2011 at 5:24 Comment(0)
C
0
<TextBlock.Text>
<MultiBinding StringFormat="{}{0} - {1}">
    <Binding Path="Title" />
    <Binding Path="Author" />
</MultiBinding>

Caligula answered 17/12, 2012 at 12:59 Comment(1)
This was suggested in another answer, but isn't available in Silverlight.Casimir
P
0

A very simple solution would be having a property in your ViewModel like this:

        public string TextblockDataProvider
    {
        get
        {
            return string.Format("{0} - {1}", Title, Author);
        }
        set { ; }
    }

and bind in xaml:

Text="{Binding TextblockDataProvider}"
Pliant answered 4/8, 2015 at 4:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.