1

I have a WPF ListBox that I am binding to a collection of Contact objects, similar to

public class Contact
{
    int ContactId { get; set; }
    int ContactType { get; set; }   // 1 = phone number, 2 = email address
    string Value { get; set; }
}

My current ListBox binding is

<ListBox Name="ContactsListBox"
    ItemsSource="{Binding Contacts, Mode=Oneway}"
    SelectedValuePath="ContactId"
    DisplayMemberPath="Value"
</ListBox>

I would like to display the phone numbers as text and emails as clickable "mailto:" type hyperlinks, but I'm unclear on how to get the binding to work the way I need.

3 Answers 3

2

What you need is conditional binding for your ListBox.

First you define two DateTemplates each for one contact type:

<ListBox.Resources>
    <DataTemplate x:Key="PhoneTemplate">
        <TextBlock Text="{Binding Value}" />
    </DataTemplate>
    <DataTemplate x:Key="MailTemplate">
        <TextBlock>
            <Hyperlink NavigateUri="{Binding Value}">
                <TextBlock Text="{Binding Value}" />
            </Hyperlink>
        </TextBlock>
    </DataTemplate>
</ListBox.Resources>

And then you define ItemTemplate with DataTrigger bounded to ContactType property:

<ListBox.ItemTemplate>
    <DataTemplate>
        <ContentControl Content="{Binding}">
            <ContentControl.Style>
                <Style TargetType="ContentControl">
                    <Style.Triggers>
                        <DataTrigger Binding="{Binding ContactType}" Value="1">
                            <Setter Property="ContentTemplate" Value="{StaticResource PhoneTemplate}" />
                        </DataTrigger>
                        <DataTrigger Binding="{Binding ContactType}" Value="2">
                            <Setter Property="ContentTemplate" Value="{StaticResource MailTemplate}" />
                        </DataTrigger>
                    </Style.Triggers>
                </Style>
            </ContentControl.Style>
        </ContentControl>
    </DataTemplate>
</ListBox.ItemTemplate>

Remember to remove DisplayMemberPath from your ListBox because you cannot use it if you set ItemTemplate.

Sign up to request clarification or add additional context in comments.

Comments

1

You need to write your ItemTemplate for ListBox.

<Window.Resources>
<DataTemplate  x:Key="MyTemplate">

     <StackPanel Orientation="Horizontal">
            <TextBlock Text="{Binding Value }"></TextBlock>
            <TextBlock>           
                <Hyperlink NavigateUri="{Binding YourString}" RequestNavigate="OnNavigate">Click here</Hyperlink>
            </TextBlock>
     </StackPanel>

<ListBox Name="ContactsListBox"
         ItemsSource="{Binding Contacts}"
         ItemTemplate="{StaticResource MyTemplate}"
</ListBox>

1 Comment

1

Define an ItemTemplate with a DataTrigger that binds to the ContactType property:

<ListBox Name="ContactsListBox" ItemsSource="{Binding Contacts, Mode=Oneway}" SelectedValuePath="ContactId">
<ListBox.ItemTemplate>
    <DataTemplate>
        <Grid>
            <TextBlock x:Name="phone" Text="{Binding Value}" />
            <TextBlock x:Name="email" Visibility="Collapsed">
                        <Hyperlink NavigateUri="{Binding Value}">
                            <Run Text="{Binding Value}" />
                        </Hyperlink>
            </TextBlock>
        </Grid>
        <DataTemplate.Triggers>
            <DataTrigger Binding="{Binding ContactType}" Value="2">
                <Setter TargetName="email" Property="Visibility" Value="Visible" />
            </DataTrigger>
        </DataTemplate.Triggers>
    </DataTemplate>
</ListBox.ItemTemplate>
</ListBox>

If you want the link to be opened in a web browser you should handle the RequestNavigate event of the Hyperlink as suggested here: Example using Hyperlink in WPF.

Also make sure that you define your properties as public:

public class Contact
{
    public int ContactId { get; set; }
    public int ContactType { get; set; }  // 1 = phone number, 2 = email address
    public string Value { get; set; }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.