【问题标题】:How to bind DataTemplate controls to ObservableCollections' item property如何将 DataTemplate 控件绑定到 ObservableCollections 的项目属性
【发布时间】:2014-12-11 12:25:22
【问题描述】:

我正在尝试创建一个自定义列表框来显示一些数据,但是我找不到在 DataTemplate 控件和项目属性之间设置绑定的正确方法。

我有以下 POCO 类:

Namespace Model
    Public Class Version

        Property Numero As String

        Property Checksum As String

    End Class
End Namespace

还有这个 ViewModel 类:

Imports System.ComponentModel
Imports System.Collections.ObjectModel

Namespace ViewModel
    Public Class VersionViewModel
        Implements INotifyPropertyChanged


        Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged


        Private _ListaVersiones As ObservableCollection(Of Model.Version)
        Public Property ListaVersiones As ObservableCollection(Of Model.Version)
            Get
                Return _ListaVersiones
            End Get
            Set(value As ObservableCollection(Of Model.Version))
                _ListaVersiones = value
                NotifyPropertyChanged("Versiones")
            End Set
        End Property

        Private Sub NotifyPropertyChanged(ByVal propertyName As String)
            RaiseEvent PropertyChanged(Me, New ComponentModel.PropertyChangedEventArgs(propertyName))
        End Sub


    End Class
End Namespace

我正在尝试在以下 XAML 中使用此 ViewModel:

<Window x:Class="MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:vm="clr-namespace:Projeto.ViewModel"
    Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded">
    <Window.Resources>
        <vm:VersionViewModel x:Key="ViewModel"/>
        <Style 
            BasedOn="{StaticResource {x:Type ListBox}}"
            TargetType="ListBox"
            x:Key="EstiloGridVersion">

            <Setter Property="ItemTemplate">
                <Setter.Value>
                    <DataTemplate>
                        <Grid Background="Blue">
                            <Border Background="Red" x:Name="border" BorderBrush="Gray" CornerRadius="6" Height="30" BorderThickness="1">

                                <!-- The error is in the Binding Path -->
                                <TextBlock Text="{Binding  Path=ListaVersiones.Numero}"/>
                            </Border>
                        </Grid>

                    </DataTemplate>
                </Setter.Value>
            </Setter>

        </Style>
    </Window.Resources>

    <ListBox x:Name="GridVersion" Style="{StaticResource EstiloGridVersion}" ItemsSource="{Binding Source={StaticResource ViewModel}, Path=ListaVersiones}">

    </ListBox>
</Window>

TextBlock 绑定选项给我一个错误“无法解析符号 X”。

这样做的正确方法是什么?

更新

这里是 Window Loaded 事件代码:

Class MainWindow

    Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
        Dim versiones As New VersionViewModel
        versiones.ListaVersiones = New ObjectModel.ObservableCollection(Of Model.Version)()
        versiones.ListaVersiones.Add(New Model.Version() With {.Numero = "07.0201", .Checksum = "0450a4s6540a6s5006a5s4"})
        versiones.ListaVersiones.Add(New Model.Version() With {.Numero = "07.0207", .Checksum = "243jkh234jh23j3406a5s4"})

        GridVersion.ItemsSource = versiones
    End Sub

End Class

【问题讨论】:

  • ItemsSourceListaVersiones 所以每个项目都是 Version 类型所以 &lt;TextBlock Text="{Binding Path=Numero}"/&gt; 应该可以工作
  • 它在设计时给出了同样的错误:无法解析符号 Numero。当应用程序执行时,它只是关闭,没有崩溃消息(同时使用 ListaVersiones.Numero 和 Numero)。
  • 它可能会在设计时给出错误(有时设计师在解决正确的上下文时遇到问题),但它应该在运行时工作。如果您的应用程序关闭,我认为是出于不同的原因,那么此绑定存在问题
  • 同样,当您为 ListaVersiones 属性提出 NotifyPropertyChanged 时,您需要传递 ListaVersiones 而不是像现在那样传递 Versiones跨度>
  • 我已经为整个应用添加了其余代码。我找不到在不显示任何错误的情况下自动关闭的理由。修复了 NotifyPropertyChanged 但应用仍然关闭。

标签: wpf vb.net xaml


【解决方案1】:

由于ItemsSource 设置为ObservableCollection&lt;Model.Version&gt;,每个项目都将是Model.Version 类型,并且对于每个ListBoxItem,这将是DataContext,因此在您的DataTemplate 中,您需要引用@987654327 的属性@

<TextBlock Text="{Binding Path=Numero}"/>

另外,它不应该编译,但问题是当你分配ItemsSource

GridVersion.ItemsSource = versiones

你应该指定versiones.ListaVersiones

GridVersion.ItemsSource = versiones.ListaVersiones

另一件事是,当您为 ListaVersiones 属性提出 NotifyPropertyChanged 时,您需要传递 ListaVersiones(确切的属性名称),而不是像在瞬间

NotifyPropertyChanged("ListaVersiones")

由于您手动设置了ItemsSource,因此您无需在 XAML 中进行设置

ItemsSource="{Binding Source={StaticResource ViewModel}, Path=ListaVersiones}"

您在 Window_Loaded 中创建的新 VersionViewModel 实例与您在 XAML 中创建的实例不同

<vm:VersionViewModel x:Key="ViewModel"/>

【讨论】:

  • 如何在我的 VB 代码中使用 实例?
  • 如果你想手动初始化一些我不会那样使用的属性。在 MainWindow 中创建 VersionViewModel 的一个实例并保存在局部变量中,例如 _myVersionViewModel。将其设置为DataContext (Me.DataContext = _myVersionViewModel) 并将ItemsSource 绑定更改为ItemsSource="{Binding Path=ListaVersiones}" 然后您可以执行_myVersionViewModel.ListaVersiones = ... 并且UI 应该更新而无需手动更新ItemsSource (GridVersion.ItemsSource = ....)
  • 你为什么说你不会这样使用它(通过设置DataContext)?这样使用有什么缺点吗?
  • 如果您想创建视图模型的实例并让它从该点开始滚动(无需手动初始化),那么在 XAML 中创建视图模型是很好的选择。但是,由于您想手动初始化 ListaVersiones,并且想要处理在 XAML 中创建的实例,那么您需要首先找到该资源并处理那些在我看来不必要的更加困难和不太清楚的资源
  • 在没有手动初始化的情况下,我应该在我的 ViewModel 中有一个命令,以便在某些情况下从 XAML 将数据加载到我的 ObservableCollection 中。对吗?
猜你喜欢
  • 1970-01-01
  • 2013-01-01
  • 2018-09-30
  • 2019-09-29
  • 2012-09-06
  • 2013-03-23
  • 2012-04-11
  • 2021-05-21
  • 2014-03-12
相关资源
最近更新 更多