我应该使用 DataTemplates 还是 UserControl 来显示扩展类的不同控件?

发布于 2024-10-07 22:22:41 字数 617 浏览 4 评论 0原文

我有一个 User 类和一个扩展 User 的 Author 类。我有一个 ObservableCollection显示在列表框中。为此,我有一个 DataTemplate 来显示每个项目,另一个 DataTemplate 来显示每个选定的项目。我还有一列 TextBoxes,它们绑定到 ListBox.SelectedItem 属性的属性。到目前为止,一切都很好。

目前,如果所选用户是作者并且一切正常,我会在列和数据模板中显示额外的控件,但我在作弊。我在 User 类中添加了 IsAuthor bool 属性,以便我可以绑定到它并确定用户是否是作者。我知道这是错误的,但我无法找到任何其他方法来做到这一点,所以我的第一个问题是如何以与基类不同的方式显示扩展类?我为作者类型尝试了不同的 DataTemplate,但它从未起作用......也许是因为该集合的类型为 User?

第二个问题是我是否应该将所有许多 TextBox 控件放在 UserControl 的列中并更改与 Author 相关的控件的可见性,或者以某种方式将它们放入 DataTemplate 中并为每种类型创建一个?我当前使用第一种方法,问题是当当前选定的项目不是作者时,绑定到 Author 属性的每个控件都会抛出错误(我可以在 Visual Studio 的输出窗口中看到它们)。

I have a User class and an Author class that extends User. I have an ObservableCollection<User> being displayed in a ListBox. For this, I have a DataTemplate to display each item and another to display each selected item. I also have a column of TextBoxes that are bound to the properties of the ListBox.SelectedItem property. So far, so good.

At the moment, I am displaying extra controls in the column and DataTemplates if the selected User is an Author and it all works fine, but I'm cheating. I have added an IsAuthor bool property into the User class so that I could bind to it and determine whether a User was an Author. I know it's wrong, but I couldn't work out any other way to do it, so my first question is how do you display extended classes differently from the base class? I tried a different DataTemplate for the type Author, but it never worked... maybe because the collection was of type User?

The second question is should I have all of the many TextBox controls in the column in a UserControl and change the Visibility of the Author related controls, or somehow put them in a DataTemplate and create one for each type? I am using the first method currently and the problem is that each control bound to an Author property is throwing errors (I can see them in the Output window in Visual Studio) when the currently selected item is not an Author.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

剪不断理还乱 2024-10-14 22:22:41

我有一个类似的设置,它使用数据模板,并且它与继承的类一起工作得很好。我就是这样做的。

<ListBox Name="UserList" ItemsSource="{Binding Path=Users}"
         ItemTemplate="{StaticResource ShowUserName}"
         SelectedItem="{Binding Path=SelectedUser, Mode=TwoWay}">
</ListBox>
<ContentControl Content="{Binding ElementName=UserList, Path=SelectedItem}"/>

在 Window.Resources 部分中,我有以下 DataTemplates:

<DataTemplate x:Key="ShowTime" DataType="TestApp.User">
    <TextBlock Text="{Binding Path=Name}" HorizontalAlignment="Center"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:User}">
   <StackPanel Margin="10">
     <TextBlock Text="{Binding Path=Name}"/>
     <TextBlock Text="{Binding Path=Age}"/>
   </StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Author}">
   <StackPanel Margin="10">
     <TextBlock Text="{Binding Path=Name}"/>
     <TextBlock Text="{Binding Path=Age}"/>
     <TextBlock Text="{Binding Path=FirstTitle}"/>
   </StackPanel>
</DataTemplate>

第一个模板将显示在列表本身中。我们在列表框的 ItemTemplate 属性中通过键引用它。内容控件在确定为所选项目显示什么内容时使用其他两个数据模板。当选择的项目只是一个用户时,将显示用户数据模板,如果选择了作者,将显示作者数据模板。

x:Type local:Author 指的是类类型。 local 应该在你的命名空间声明中声明。

xmlns:local="clr-namespace:TestApp"

请记住,这是我的命名空间,您必须指定您正在使用的命名空间。当然,数据模板只是基本示例,想必您会想要做一些更适合您的应用程序的事情。

然而,必须为两个类定义几乎完全相同的两个单独的数据模板可能会令人恼火。虽然你当然可以。我在自己的应用程序中执行此操作(不在本例中),因为我想要为每种类型显示的内容有很大不同。

因此,可能有用的是为所有用户属性创建一个通用的数据模板,并简单地为作者扩展此数据模板。如果你想这样做,你可以这样设置你的模板:

<DataTemplate x:Key="UserTemplate">
  <!-- show all the properties of the user class here -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:User}">
  <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource UserTemplate}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Author}">
  <StackPanel>
    <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource UserTemplate}"/>
    <!-- show all the additional Author properties here -->
  </StackPanel>
</DataTemplate>

正如你所看到的,用户和作者的数据模板都开始使用名为“UserTemplate”的数据模板。但在作者数据模板中,我们将添加作者特定的属性。

我希望这有帮助。

I have a similar setup which uses data templates and it works just fine with inherited classes. This is how I did it.

<ListBox Name="UserList" ItemsSource="{Binding Path=Users}"
         ItemTemplate="{StaticResource ShowUserName}"
         SelectedItem="{Binding Path=SelectedUser, Mode=TwoWay}">
</ListBox>
<ContentControl Content="{Binding ElementName=UserList, Path=SelectedItem}"/>

In the Window.Resources section I have the following DataTemplates:

<DataTemplate x:Key="ShowTime" DataType="TestApp.User">
    <TextBlock Text="{Binding Path=Name}" HorizontalAlignment="Center"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:User}">
   <StackPanel Margin="10">
     <TextBlock Text="{Binding Path=Name}"/>
     <TextBlock Text="{Binding Path=Age}"/>
   </StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Author}">
   <StackPanel Margin="10">
     <TextBlock Text="{Binding Path=Name}"/>
     <TextBlock Text="{Binding Path=Age}"/>
     <TextBlock Text="{Binding Path=FirstTitle}"/>
   </StackPanel>
</DataTemplate>

The first template is what will be displayed in the list itself. We are referencing it by key in the ItemTemplate property of the listbox. The other two data templates are used by the content control when determining what to display for the selected item. When the selected item is just a User, the User DataTemplate will be displayed, if an author is selected, the author DataTemplate will be shown.

The x:Type local:Author is referring to the the class type. local should be declared in your namespace declarations.

xmlns:local="clr-namespace:TestApp"

Keep in mind that this is my namespace, you will have to specify the one you are using. And of course the data templates are just basic examples, presumably you will want to do something more tailored to your application.

However it might be irritating to have to define two separate Data templates that are almost exactly the same for your two classes. Although you certainly could. I do it in my own application (not in this example), because what I want to display for each type are vastly different.

So what might be useful is to create a common DataTemplate for all the User properties, and simply extend this DataTemplate for Authors. If you want to do that you could set up your templates this way:

<DataTemplate x:Key="UserTemplate">
  <!-- show all the properties of the user class here -->
</DataTemplate>
<DataTemplate DataType="{x:Type local:User}">
  <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource UserTemplate}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Author}">
  <StackPanel>
    <ContentPresenter Content="{Binding}" ContentTemplate="{StaticResource UserTemplate}"/>
    <!-- show all the additional Author properties here -->
  </StackPanel>
</DataTemplate>

So as you can see, both of the DataTemplates for User and for Author start out using the DataTemplate called "UserTemplate". But in the Author DataTemplate we will add Author specific properties.

I hope that helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文