我有两种对象类型显示在同一选项卡中的选项卡上。我正在使用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();
}
}
}
有谁知道我为什么会收到这些错误以及如何修复代码?
答案 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>