System.Windows.Data错误:40:BindingExpression路径错误

时间:2015-10-21 01:39:03

标签: wpf

我有两种对象类型显示在同一选项卡中的选项卡上。我正在使用DataTrigger和DataTypeConverter来显示内容。内容显示正确,但我在输出窗口中收到以下错误:

System.Windows.Data Error: 40 : BindingExpression path error: 'Taste' property not found on 'object' ''MySmellObject' (HashCode=30266853)'. BindingExpression:Path=Taste; DataItem='MySmellObject' (HashCode=30266853); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String')
System.Windows.Data Error: 40 : BindingExpression path error: 'Smell' property not found on 'object' ''MyTasteObject' (HashCode=36404074)'. BindingExpression:Path=Smell; DataItem='MyTasteObject' (HashCode=36404074); target element is 'TextBox' (Name=''); target property is 'Text' (type 'String')

这是XAML:

<Window x:Class="ControlTest.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:ControlTest"
        Title="MainWindow" Height="350" Width="525">

<Window.Resources>
    <local:DataTypeConverter x:Key="DataTypeConverter" />
</Window.Resources>

<StackPanel Orientation="Vertical" Width="150">
    <TabControl Name="tab" Height="200px"
            ItemsSource="{Binding MyObjects}"                 
            SelectedValuePath="Id"
            SelectedItem="{Binding MyObject}"
            >            
        <TabControl.ContentTemplate>
            <DataTemplate>
                <ContentControl>
                    <ContentControl.Style>
                        <Style TargetType="ContentControl">
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding ElementName=tab,Path=SelectedItem, Converter={StaticResource DataTypeConverter}}" Value="{x:Type local:MyTasteObject}">
                                    <Setter Property="Content">
                                        <Setter.Value>
                                            <TextBox Text="{Binding Taste}" ></TextBox>
                                        </Setter.Value>
                                    </Setter>
                                </DataTrigger>
                                <DataTrigger Binding="{Binding ElementName=tab,Path=SelectedItem, Converter={StaticResource DataTypeConverter}}" Value="{x:Type local:MySmellObject}">
                                    <Setter Property="Content">
                                        <Setter.Value>
                                            <TextBox Text="{Binding Smell}" ></TextBox>
                                        </Setter.Value>
                                    </Setter>
                                </DataTrigger>                                    
                            </Style.Triggers>
                        </Style>
                    </ContentControl.Style>
                </ContentControl>
            </DataTemplate>
        </TabControl.ContentTemplate>
    </TabControl>
</StackPanel>
</Window>

这里有代码:

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace ControlTest
{
    public partial class MainWindow : Window
    {
        public List<MyObject> MyObjects { get; set; }

        public int MyObjectId { get; set; }
        public MyObject MyObject { get; set; }

        public MainWindow()
        {
            MyObject obj0 = new MySmellObject() { Id = 0, Smell = "Pleasent" };
            MyObject obj1 = new MyTasteObject() { Id = 1, Taste = "Mild" };

            MyObjects = new List<MyObject> { obj0, obj1 };
            MyObjectId = 0;
            MyObject = obj0;

            DataContext = this;

            InitializeComponent();
        }
    }

    public class MyObject
    {
        public int Id { get; set; }
    }

    public class MyTasteObject : MyObject
    {
        public string Taste { get; set; }

        public override string ToString()
        {
            return Taste;
        }
    }

    public class MySmellObject : MyObject
    {
        public String Smell { get; set; }

        public override string ToString()
        {
            return Smell;
        }
    }

    public class DataTypeConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter,
            CultureInfo culture)
        {
            return value.GetType();
        }

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

有谁知道我为什么会收到这些错误以及如何修复代码?

1 个答案:

答案 0 :(得分:2)

此处的问题是ContentTemplate适用于TabControl中的所有项目。最初它仅应用于SelectedItem。但在切换到新项目后,它会应用于所有已加载的项目。

更改SelectedItem后,更新了具有新ContentTemplate的ContentControl的Content,然后将其应用于所有项目。但是因为底层物品具有不同的具体类型(源自相同的基础类型)。因此,一旦模板应用于不匹配类型的项目,将以静默方式报告绑定错误。

事实上,我们有一种更好的方法来实现你想要的,而根本不使用触发器。这就是所谓的DataTemplate为您提供的。只需将DataType设置为项目类型,然后它就会自动替换为相应的模板,如下所示:

<TabControl.ContentTemplate>
    <DataTemplate>                
        <ContentControl Content="{TemplateBinding Content}">
            <ContentControl.Resources>
                <DataTemplate DataType="{x:Type local:MySmellObject}">
                    <TextBox Text="{Binding Smell}" ></TextBox>
                </DataTemplate>
                <DataTemplate DataType="{x:Type local:MyTasteObject}">
                    <TextBox Text="{Binding Taste}" ></TextBox>
                </DataTemplate>
            </ContentControl.Resources>
        </ContentControl>
    </DataTemplate>
</TabControl.ContentTemplate>