MVVM WPF datagrid选择绑定到具有复杂对象的组合框

时间:2017-02-03 02:25:12

标签: wpf vb.net mvvm combobox datagrid

我正在尝试实现一个DataGrid,其中一个列具有复杂对象,而comboBox(在网格外)具有此列的同一时间对象的列表。使用WPF和MVVM。

当我在数据网格中选择Line时,我希望组合框显示相应的值。

但我不知道我做错了什么。 有人可以帮忙吗?

    <ComboBox x:Name="cmbResourceList" 
              HorizontalAlignment="Left" 
              ItemsSource="{Binding MainListSource}"
              DisplayMemberPath="Description"
                SelectedValue="{Binding Path=ScheduleVM.Schedule.ResourceList}"
              Width="185"/>

    <DataGrid x:Name="dgScheduleItems"   
              AutoGenerateColumns="False" 
              ItemsSource="{Binding Path=ScheduleSource}" 
              SelectionMode="Single"
              IsReadOnly="True"
              SelectedItem="SelectedSchedule">

        <DataGrid.Columns>
            <DataGridTextColumn Header="Id"             Binding="{Binding Id}"                          Width="40"/>
            <DataGridTextColumn Header="Resource List"  Binding="{Binding ResourceList.Description}"    Width="*"/>
            <DataGridTextColumn Header="Task List"      Binding="{Binding TaskList.Description}"        Width="*"/>
            <DataGridTextColumn Header="Description"    Binding="{Binding Description}"                 Width="100"/>
        </DataGrid.Columns>

    </DataGrid>

这里是Vb.Net中的课程

Public Class MainList
    Public Property Id As Integer
    Public Property Description As String
End Class


Public Class Schedule
    Public Property Id As Integer
    Public Property Description As String
    Public Property ResourceList As MainList
    Public Property TaskList As MainList
End Class


Public Class MainListRepository
    Private _mainLists As List(Of MainList)

    Public Sub New()
        _mainLists = New List(Of MainList) From
        {
            New MainList() With {.Id = 1, .Description = "First List"},
            New MainList() With {.Id = 2, .Description = "Second List"},
            New MainList() With {.Id = 3, .Description = "Third List"}
        }
    End Sub

    Public Function GetMainLists() As List(Of MainList)
        Return _mainLists
    End Function
End Class


Public Class ScheduleRepository
    Private _schedules As List(Of Schedule)

    Public Sub New()
        _schedules = New List(Of Schedule) From
        {
            New Schedule() With {.Id = 1, .Description = "Schedule 1", .ResourceList = New MainList() With {.Id = 2, .Description = "Second List"}, .TaskList = New MainList() With {.Id = 1, .Description = "First List"}},
            New Schedule() With {.Id = 2, .Description = "Schedule 2", .ResourceList = New MainList() With {.Id = 1, .Description = "First List"}, .TaskList = New MainList() With {.Id = 2, .Description = "Second List"}},
            New Schedule() With {.Id = 3, .Description = "Schedule 3", .ResourceList = New MainList() With {.Id = 1, .Description = "First List"}, .TaskList = New MainList() With {.Id = 3, .Description = "Third List"}},
            New Schedule() With {.Id = 4, .Description = "Schedule 4", .ResourceList = New MainList() With {.Id = 3, .Description = "Third List"}, .TaskList = New MainList() With {.Id = 1, .Description = "First List"}}
        }
    End Sub

    Public Function GetSchedules() As List(Of Schedule)
        Return _schedules
    End Function
End Class

Public MustInherit Class ViewModelBase
    Implements INotifyPropertyChanged

    Protected Sub New()
    End Sub

    Public Event PropertyChanged As PropertyChangedEventHandler Implements INotifyPropertyChanged.PropertyChanged

    Protected Overridable Sub OnPropertyChanged(ByVal propertyName As String)
        Me.VerifyPropertyName(propertyName)

        Dim handler As PropertyChangedEventHandler = Me.PropertyChangedEvent
        If handler IsNot Nothing Then
            Dim e = New PropertyChangedEventArgs(propertyName)
            handler(Me, e)
        End If
    End Sub

    Private privateThrowOnInvalidPropertyName As Boolean
    Protected Overridable Property ThrowOnInvalidPropertyName() As Boolean
        Get
            Return privateThrowOnInvalidPropertyName
        End Get
        Set(ByVal value As Boolean)
            privateThrowOnInvalidPropertyName = value
        End Set
    End Property
End Class

Public Class ScheduleVM
    Inherits ViewModelBase

    Private _Schedule As Schedule
    Public Property Schedule() As Schedule
        Get
            Return _Schedule
        End Get
        Set(ByVal value As Schedule)
            _Schedule = value

            OnPropertyChanged("Schedule")
        End Set
    End Property

    Public Sub New(schedule As Schedule)
        _Schedule = schedule
    End Sub

End Class


Friend Class SchedulePopupVM
    Inherits ViewModelBase

    Private _ScheduleSource As List(Of Schedule)
    Public Property ScheduleSource() As List(Of Schedule)
        Get
            Return _ScheduleSource
        End Get
        Set(ByVal value As List(Of Schedule))
            _ScheduleSource = value

            OnPropertyChanged("ScheduleSource")
        End Set
    End Property

    Private _MainListSource As List(Of MainList)
    Public Property MainListSource() As List(Of MainList)
        Get
            Return _MainListSource
        End Get
        Set(ByVal value As List(Of MainList))
            _MainListSource = value

            OnPropertyChanged("MainListSource")
        End Set
    End Property


    Private _SelectedSchedule As Schedule
    Public Property SelectedSchedule() As Schedule
        Get
            Return _SelectedSchedule
        End Get
        Set(ByVal value As Schedule)
            _SelectedSchedule = value
            Me.ScheduleVM = New ScheduleVM(value)

            OnPropertyChanged("SelectedSchedule")
        End Set
    End Property

    Private _ScheduleVM As ScheduleVM
    Public Property ScheduleVM() As ScheduleVM
        Get
            Return _ScheduleVM
        End Get
        Set(ByVal value As ScheduleVM)
            _ScheduleVM = value

            OnPropertyChanged("ScheduleVM")
        End Set
    End Property

    Public Sub New()
        Dim repo As ScheduleRepository = New ScheduleRepository()
        Dim repoMain As MainListRepository = New MainListRepository()

        _ScheduleSource = repo.GetSchedules()
        _MainListSource = repoMain.GetMainLists()

    End Sub

End Class

1 个答案:

答案 0 :(得分:1)

一些事情。

您的SelectedValues(在您的ComboBox上)都绑定到项目集合。您不希望这样,这些属性旨在绑定到项集合中的各个项目。

接下来,您对SelectedItem的{​​{1}}的绑定是错误的。将其更新为(注意绑定关键字和大括号):

DataGrid

接下来,对于您的 <DataGrid x:Name="dgScheduleItems" AutoGenerateColumns="False" ItemsSource="{Binding Path=ScheduleSource}" SelectionMode="Single" IsReadOnly="True" SelectedItem="{Binding SelectedSchedule}" Margin="0,106,0,0"> ,您希望绑定到单个值。但是,您绑定到ComboBoxes的值必须是对其ItemsSource中某个值的引用。

更新它们以绑定到新属性。例如:

SelectedValue

然后,在SelectedSchedule属性更改时设置NEW属性(MainListSourceSelectedValue)。像(在c#中)

的东西
   <ComboBox x:Name="cmbTaskList" 
            HorizontalAlignment="Left" 
            ItemsSource="{Binding MainListSource}"
            DisplayMemberPath="Description"
            SelectedValue="{Binding MainListSourceSelectedValue, Mode=TwoWay}"
            Margin="244,30,0,0" 
            VerticalAlignment="Top" 
            Width="185"/>