2017-02-03 3 views
-1

Ich versuche, ein DataGrid zu implementieren, das eine der Spalten ein komplexes Objekt und die ComboBox (außerhalb des Rasters) eine Liste des gleichen Zeitobjekts dieser Spalte hat . Verwenden von WPF und MVVM.MVVM WPF Datagrid Ausgewählte Bindung an Combobox mit komplexem Objekt

Wenn ich die Zeile im Datagrid auswähle, möchte ich, dass das Kombinationsfeld den entsprechenden Wert anzeigt.

Aber ich weiß nicht was ich falsch mache. Kann jemand helfen?

<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> 

Und hier die Klassen in 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 
+0

Warum heruntergeregelt? Hinterlasse einen Kommentar mindestens – andrepaulo

+0

Der meiste Code zur Verfügung gestellt scheint nicht notwendig, um Ihr Problem zu reproduzieren, noch ist es ausreichend. Dies hat zwei Hauptnachteile 1) Der Leser hat die Aufgabe zu filtern, was relevant ist von dem, was nicht ist 2) Es macht es unwahrscheinlich, dass Sie Frage zu einer anderen Person als nur Sie (wie es ist nicht allgemein) hilfreich ist. Wenn Sie nicht in der Lage sind, nur durch Raten zu korrigieren, besteht der erste Schritt darin, sie zu isolieren, indem Sie schrittweise Code entfernen, bis Sie nichts mehr entfernen können, ohne den Fehler zu entfernen. Wenn Sie dann immer noch nicht sehen können, was falsch ist, geben Sie den resultierenden Code und Ihre Frage ein. – franssu

+0

@franssu Ich versuchte mein Bestes, um es so kurz wie möglich zu machen, danke für deinen Kommentar. Ich möchte nur klarstellen, dass die Leute hier die aktuellen Einschränkungen der "Fragesteller" respektieren sollten und wir wissen, wenn jemand fragt, ob er faul ist oder nicht. BTW Ich habe den Code der Frage geändert, um Ihren Anforderungen zu entsprechen. – andrepaulo

Antwort

1

Ein paar Dinge.

Beide Ihrer SelectedValues (auf Ihrer ComboBox) sind an Artikel Sammlungen gebunden. Das möchten Sie nicht, diese Eigenschaften sollen an einzelne Artikel innerhalb der Artikelsammlung gebunden sein.

Als nächstes ist Ihre Bindung für die SelectedItem Ihrer DataGrid falsch. Aktualisieren Sie es (Mitteilung verbindlich Stichwort und Klammern):

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

nächstes für Ihre ComboBoxes Sie dann auf einen einzelnen Wert binden möchten. Der für SelectedValue bindende Wert muss jedoch ein Verweis auf einen der Werte in ItemsSource sein.

Aktualisieren Sie diese, um sie an eine NEUE Eigenschaft zu binden. Beispiel:

<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"/> 

Dann stellen Sie die neue Eigenschaft (MainListSourceSelectedValue), wenn die SelectedSchedule Eigenschaft ändert. Etwas wie (in C#)

public MainList MainListSourceSelectedValue 
{ 
    get { return _mainListSourceSelectedValue; } 
    set 
    { 
     if (_mainListSourceSelectedValue == value) return; 
     _mainListSourceSelectedValue = value; 

     RaisePropertyChanged(); 
    } 
} 

public Schedule SelectedSchedule 
{ 
    get { return _selectedSchedule; } 
    set 
    {   
     if (_selectedSchedule == value) return; 
     _selectedSchedule = value; 

     foreach (var mainListItem in MainList) 
     { 
      if (mainListItem.Description.equals(_selectedSchedule.ResourseList.Description)) 
      { 
       MainListSourceSelectedValue = mainListItem; 
       break; 
      } 
     } 

     RaisePropertyChanged(); 
    } 
} 
+0

Es hat funktioniert, aber ich muss ein wenig Ihren Code ändern ... Kann ich meine Combos nicht an ein Eigenschaftsobjekt meines 'SelectedSchedule' binden? Muss ich immer eine neue Eigenschaft in meiner VM zum Binden deklarieren? – andrepaulo

+0

Ich schlug einige Änderungen an Ihrer Antwort vor, also sollte dies funktionieren – andrepaulo

+0

Vielen Dank für Ihre Hilfe @ d.moncada – andrepaulo