具有条件显示的WPF ListBox绑定

WPF ListBox binding with conditional display

我有一个WPF ListBox,我将其绑定到Contact对象的集合,类似于

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

我当前的ListBox绑定是

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

我想将电话号码显示为文本,并将电子邮件显示为可单击的" mailto:"类型的超链接,但是我不清楚如何使绑定按我需要的方式工作。


使用绑定到ContactType属性的DataTrigger定义ItemTemplate:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<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>

如果要在Web浏览器中打开链接,则应按照此处的建议处理Hyperlink的RequestNavigate事件:在WPF中使用Hyperlink的示例。

还要确保将属性定义为public:

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


您需要的是ListBox的条件绑定。

首先,为一种接触类型分别定义两个DateTemplate

1
2
3
4
5
6
7
8
9
10
11
12
<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>

然后使用DataTrigger绑定到ContactType属性定义ItemTemplate

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<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>

请记住从ListBox中删除DisplayMemberPath,因为如果设置了ItemTemplate,则无法使用它。


您需要为ListBox编写ItemTemplate。

1
2
3
4
5
6
7
8
9
<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>

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