如何为多种对象类型显示不同的WPF DataTemplate

时间:2015-10-08 18:02:03

标签: wpf binding combobox datatemplate

以下博客文章演示了如何动态显示不同的DataTemplate,具体取决于ListBox中显示的对象:

http://www.thejoyofcode.com/different_datatemplates_for_different_types.aspx

虽然这很有用,但我的具体情况更具挑战性。

我的主视图模型中有一组对象:

public IEnumerableCollection<IGenericObject> CurrentObjects

我目前使用XAML在ComboBox中显示它们,如下所示:

<ComboBox ItemsSource="{Binding CurrentObjects}"
          SelectedItem="{Binding SelectedObject, 
                                 Mode=TwoWay, 
                                 UpdateSourceTrigger=PropertyChanged }"
          DisplayMemberPath="Name"
          SelectedIndex="0"/>

我现在希望在ComboBox下面有一个单独的面板,它显示每个对象的属性。但是,每个对象具有不同的属性,具体取决于其具体类型。

例如,AObject不仅支持IGenericObject,还支持IAObject,因此我希望始终显示所有对象共有的属性,然后动态显示所有对象的属性特定于当前选择的任何对象。

我不知道如何设置绑定并获取每个特定对象类型的属性值,因为我使用了常见的IGenericObject接口。

我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:1)

  

显示每个对象的属性。

请记住,在流程结束时绑定只是反思。可以放置属性名称,如果绑定失败,则不显示任何内容。

  

但是,每个对象具有不同的属性,具体取决于其具体类型。

最终我们使用转换器来隐藏标签和文本块,具体取决于组合框中所选项目所包含的目标类型。

示例

此示例是与FirstLastPhone共享相同属性的人员和员工,但员工与此人不同EmployeeId。我们希望显示两者的名字和姓氏,但如果其员工也显示其ID。还要换掉标题,说明它是员工还是个人。

组合中的姓氏,两个对象,Smith是一个人,Man是一名员工。因此,当我们有一个人时,屏幕会显示:

enter image description here

当一名员工用最后信息的ID显示时:

enter image description here

<强>的Xaml

<Page x:Class="WPFStack.Views.BindingCoverterPage"
      ... 
      xmlns:local="clr-namespace:WPFStack.Views"
      xmlns:model="clr-namespace:WPFStack.Model"
      xmlns:converter="clr-namespace:WPFStack.Converters"
      .>
<Page.Resources>
    <model:People x:Key="people">
        <model:Person First="Joe"
                        Last="Smith"
                        Phone="303-555-5555" />
    </model:People>
    <model:Employees x:Key="employeePeople">
        <model:Employee First="Omega"
                        Last="Man"
                        Phone="303-867-5309"
                        EmployeeId="90125" />
    </model:Employees>
    <converter:EmployeeVisiblity x:Key="isEmployeeVisibility"/>
    <Style x:Key="LabelStyle" TargetType="Label" >
        <Setter Property="Margin" Value="-20,0,0,0"/>
        <Setter Property="FontWeight" Value="Bold"/>
    </Style>
</Page.Resources>

<StackPanel Margin="10"
            HorizontalAlignment="Left">
    <ComboBox Name="mySelectionCombo"
                SelectedItem="{Binding SelectedObject, 
                        Mode=TwoWay, 
                        UpdateSourceTrigger=PropertyChanged }"
                DisplayMemberPath="Last"
                SelectedIndex="0"
                Width="200">
        <ComboBox.ItemsSource>
            <CompositeCollection>
                <CollectionContainer Collection="{Binding Source={StaticResource people}}" />
                <CollectionContainer Collection="{Binding Source={StaticResource employeePeople}}" />
            </CompositeCollection>
        </ComboBox.ItemsSource>
    </ComboBox>

    <StackPanel Margin="10">

        <Label Content="Employee Stats:"
                Style="{StaticResource LabelStyle}"
                Visibility="{Binding SelectedItem, 
                            ElementName=mySelectionCombo,
                            Converter={StaticResource isEmployeeVisibility}}" />

        <Label Content="Person Stats:"
                Style="{StaticResource LabelStyle}"
                Visibility="{Binding SelectedItem, 
                            ElementName=mySelectionCombo,
                            ConverterParameter=Reverse,
                            Converter={StaticResource isEmployeeVisibility}}" />

        <TextBlock Text="{Binding SelectedItem.First, ElementName=mySelectionCombo}" />
        <TextBlock Text="{Binding SelectedItem.Last, ElementName=mySelectionCombo}" />
        <TextBlock Text="{Binding SelectedItem.EmployeeId, ElementName=mySelectionCombo}"
                    Visibility="{Binding SelectedItem, 
                            ElementName=mySelectionCombo,
                            Converter={StaticResource isEmployeeVisibility}}" />
    </StackPanel>
</StackPanel>
</Page>

<强>转换器

namespace WPFStack.Converters
{
public class EmployeeVisiblity : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var isVisible = Visibility.Collapsed;

        if (value != null)
            if (value is Employee)
            {
                if (parameter == null) // Does not say string "Reverse"
                    isVisible = Visibility.Visible;
            }
        else // Value is a person
            {
                if (parameter != null) // Does say string "Reverse"
                    isVisible = Visibility.Visible;
            }

        return isVisible;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value;
    }
}
}

<强>用法

请注意,该示例主要执行的操作只是绑定到类似(但与数据不同的类型)它是进程,而不是需要的数据专注于来回答问题。

即使我使用复合集合通过ItemsSource来保存诸如你的数据集,我最终(像你一样)有一个不同的实例对象的列表,就像你的数据。

...所以

关注这一点,看看转换器如何工作以确定哪些可见,哪些不依赖于组合框选择的内容。

以下步骤需要实施和理解,以使其在您的代码中运行:

  1. 制作类似项目中的转换器。请注意命名空间。
  2. 制作xaml导入参考并将其命名为转换器。我的命名空间为WPFStack.Converters,因此将其带入Xaml使我xmlns:converter="clr-namespace:WPFStack.Converters"
  3. 在您创建的转换器的Xaml中创建一个静态实例,方法是在页面资源<converter:EmployeeVisiblity x:Key="isEmployeeVisibility"/>中指定它。
  4. 您需要隐藏的屏幕上的任何视觉控件,其Visbility属性将绑定到当前所选的组合项(您可能需要提供绑定的名称)以及调用转换器以确定它是否显示,例如此xaml代码:

    <TextBlock Text="{Binding SelectedItem.EmployeeId, ElementName=mySelectionCombo}" Visibility="{Binding SelectedItem, ElementName=mySelectionCombo, Converter={StaticResource isEmployeeVisibility}}" />

  5. 这是您需要从此回复中得到的内容。