基于DataType的DataTemplate不起作用并导致其他问题

本文关键字:其他 问题 不起作用 DataType DataTemplate 基于 | 更新日期: 2023-09-27 17:57:53

我有一个TabControl,它的ItemsSource绑定到对象类型的ObservableCollection。我这样做的唯一原因是,我可以把Property和Tennant(请忽略拼写错误的)类都放在这个列表中。我的TabControl需要根据类型有两个不同的选项卡。到目前为止,我拥有的是:

<view:CustomTabControl ItemsSource="{Binding OpenTabs}" Grid.Column="1" x:Name="Tabs">
    <view:CustomTabControl.Resources>
        <DataTemplate DataType="{x:Type model:Tennant}">
            <ScrollViewer>
                <Grid>
                    <TextBlock Text="{Binding name}"/>
                </Grid>
            </ScrollViewer>
        </DataTemplate>
        <DataTemplate DataType="{x:Type model:Property}">
            <ScrollViewer>
                <Grid MinWidth="350">
                    <!-- All of the stuff that works for the Property layout in here -->
                </Grid>
            </ScrollViewer>
        </DataTemplate>
    </view:CustomTabControl.Resources>
</view:CustomTabControl>

它非常适合Property类,但不适合Tennant类。此外,我有一个不得不ListBox的侧面。一个用于房地产,一个用于坦南特。当我将Tennant添加到Tennant的列表中时,它会显示在那里,但不会显示我指定的Tennant名称,如下所示:

<ScrollViewer VerticalScrollBarVisibility="Auto">
    <StackPanel>
        <TextBlock Margin="10,5" Text="Properties" FontSize="16"/>
        <ListBox x:Name="propertiesList" ItemsSource="{Binding Properties, Mode=TwoWay}">
            <ListBox.ItemTemplate>
                <DataTemplate DataType="{x:Type model:Property}">
                    <TextBlock Text="{Binding title}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
        <TextBlock Margin="10,5" Text="Tennants" FontSize="16"/>
        <ListBox x:Name="tennantsList" ItemsSource="{Binding Tennants, Mode=TwoWay}">
            <ListBox.ItemTemplate>
                <DataTemplate DataType="{x:Type model:Tennant}">
                    <TextBlock Text="{Binding name}"/>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </StackPanel>
</ScrollViewer>

据我所见,Tennant类与Property类几乎完全相同,当然除了它存储的信息之外,但似乎没有任何东西与Tennant对象正确绑定。我需要更改什么?我的坦南特课有什么问题吗?或者我的xaml有什么问题吗?以下是Tennant类,转述如下,供参考:

[Serializable]
public class Tennant : ISerializable, INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private bool current;
    private string name;
    private string phone;
    private string email;
    private string occupation;
    public bool Current { get { return current; } set { current = value; OnPropertyChanged("Current"); } }
    public string Name { get { return name; } set { name = value; OnPropertyChanged("Name"); } }
    public string Phone { get { return phone; } set { phone = value; OnPropertyChanged("Phone"); } }
    public string Email { get { return email; } set { email = value; OnPropertyChanged("Email"); } }
    public string Occupation { get { return occupation; } set { occupation = value; OnPropertyChanged("Occupation"); } }
    public Tennant()
    {
    }
    public Tennant(bool current, string name, string phone, string email, string occupation)
    {
        this.Current = current;
        this.Name = name;
        this.Phone = phone;
        this.Email = email;
        this.Occupation = occupation;
    }
    private void OnPropertyChanged(string p)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(p));
        }
    }
    public override string ToString()
    {
        return "" + Current + " " + Name + " " + Phone + " " + Email + " " + Occupation;
    }
    public Tennant(SerializationInfo info, StreamingContext context)
    {
        this.Current = (bool)info.GetValue("Current", typeof(bool));
        this.Name = (string)info.GetValue("Name", typeof(string));
        this.Phone = (string)info.GetValue("Phone", typeof(string));
        this.Email = (string)info.GetValue("Email", typeof(string));
        this.Occupation = (string)info.GetValue("Occupation", typeof(string));
    }
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Current", this.Current);
        info.AddValue("Name", this.Name);
        info.AddValue("Phone", this.Phone);
        info.AddValue("Email", this.Email);
        info.AddValue("Occupation", this.Occupation);
    }
}

编辑:以下是仅供参考的属性对象:

public class Property : ISerializable
{
    public string address { get; set; }
    public string city { get; set; }
    public string postcode { get; set; }
    // ...
    public Property()
    {
        // ...
    }
    public string toString()
    {
        return title;
    }
    public bool hasPhotos()
    {
        return false;
    }
    public bool hasTennant()
    {
        return false;
    }
    public void addTennant(Tennant tennant)
    {
        tennants.Add(tennant);
    }
    public void addPhoto(Photo photo)
    {
        photos.Add(photo);
    }
    public void addIssue(Problem issue)
    {
        issues.Add(issue);
    }
    public Property(SerializationInfo info, StreamingContext context)
    {
        // ...
    }
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        // ...
    }
}

我的代码出了什么问题?因为经过几个小时的搜寻,我什么也找不到。提前谢谢。

编辑2:我添加了Tennant类的其余部分。此外,我的选项卡是带有关闭按钮的自定义选项卡,当我单击选项卡控件旁边的一个tennant列表框项目时,它会打开一个空的可关闭选项卡。侧面的属性列表框项目会打开一一个完全可关闭的选项卡。然后,我可以关闭属性选项卡,但不能关闭tennant选项卡。以下是我添加到OpenTabs对象ObservableCollection的代码:

// Inside the Constructor
OpenTabs = new ObservableCollection<Object>();
EventManager.RegisterClassHandler(typeof(ListBoxItem),
    ListBoxItem.MouseLeftButtonDownEvent,
    new RoutedEventHandler(this.OnMouseLeftButtonDown));
private void OnMouseLeftButtonDown(object sender, RoutedEventArgs e)
{
    ListBoxItem selected = sender as ListBoxItem;
    try
    {
        string t = (selected.Content as Property).title;
        Property cur = selected.Content as Property;
        OpenProperty(cur);
    }
    catch (NullReferenceException nre)
    {
        Tennant cur = selected.Content as Tennant;
        OpenTennant(cur);
    }
}
// This method opens a new tab with a Property's details in it
private void OpenProperty(Property property)
{
    this.HomeView.Visibility = System.Windows.Visibility.Hidden;
    this.TabbedView.Visibility = System.Windows.Visibility.Visible;
    MainWindow.OpenTabs.Add(property);
    this.Tabs.SelectedIndex = MainWindow.OpenTabs.IndexOf(property);
}
// This method opens a new tab with a Tennant's details in it
private void OpenTennant(Tennant tennant)
{
    this.HomeView.Visibility = System.Windows.Visibility.Hidden;
    this.TabbedView.Visibility = System.Windows.Visibility.Visible;
    MainWindow.OpenTabs.Add(tennant);
    this.Tabs.SelectedIndex = MainWindow.OpenTabs.IndexOf(tennant);
}

希望能有所帮助。问问你是否想要更多。

编辑3:现在我已经向xaml添加了上下文,还向上面更新的Tennant类添加了INotifyPropertyChanged。我还忘了添加一个事实,即两个`DataTemplates是分开的。如在中用GridSplitter分隔。

编辑4:我仍在寻找这个问题的答案,因为我的问题仍然存在,尽管我已经尽我所能实现了所有建议的答案。

基于DataType的DataTemplate不起作用并导致其他问题

您需要使Tennant类实现INotifyPropertyChanged。否则,在支持类中所做的更改将不会反映在UI中,这听起来可能是您的问题。

您为Tennant显示了两个不同的隐式DataTemplates,但不是在声明它们的位置。如果它们最终都在范围内(或者都不在范围内),您可能会得到一个您不期望的(或者没有模板)。