2017-02-03 11 views
-1

Я пытаюсь реализовать DataGrid, когда один из столбцов имеет сложный объект, а comboBox (вне сетки) имеет список одного и того же объекта времени этого столбца , Использование WPF и MVVM.MVVM WPF datagrid Выбранная привязка к combobox со сложным объектом

Когда я выбираю строку в datagrid, я хочу, чтобы поле со списком отображало соответствующее значение.

Но я не знаю, что я делаю неправильно. Может ли кто-нибудь помочь?

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

Почему downvoted? оставьте комментарий как минимум – andrepaulo

+0

Большая часть предоставленного кода не кажется необходимой для воспроизведения вашей проблемы, и она не достаточна. Это имеет два основных недостатка: 1) Читатель должен выполнить задачу фильтрации того, что уместно из того, что не является 2). Это делает маловероятным, чтобы вы задавали вопрос кому-либо другому, кроме как только вы (поскольку он не является общим). Если вы не можете правильно исправить, просто догадавшись, первым шагом является его изоляция путем постепенного удаления кода, пока вы не сможете удалить что-либо еще, не удаляя ошибку. Тогда, если вы все еще не можете понять, что не так, отправьте полученный код и ваш вопрос. – franssu

+0

@franssu Я пробовал изо всех сил, чтобы сделать его максимально лаконичным, спасибо за ваш комментарий. Я просто хочу сказать, что люди здесь должны уважать нынешние ограничения «адеков», и мы знаем, когда кто-то просит лениться или нет. BTW Я изменил код вопроса в соответствии с вашими требованиями. – andrepaulo

ответ

1

несколько вещей.

Оба ваших SelectedValues (на вашем ComboBox) привязаны к коллекциям предметов. Вы не хотите этого, эти свойства предназначены для привязки к отдельным элементам коллекции элементов.

Дальше, ваша привязка для SelectedItem вашего DataGrid неверна. Обновите его (уведомление связывания ключевого слова и скобки):

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

Далее, для ComboBoxes, то вы хотите привязать к отдельному значению. Хотя значение, которое вы связываете для SelectedValue, должно быть ссылкой на одно из значений в его ItemsSource.

Обновите их, чтобы привязать к новому объекту. Пример:

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

Затем установите новое свойство (MainListSourceSelectedValue) при изменении SelectedSchedule свойств. Что-то вроде (в 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

Это сработало, но мне нужно немного изменить ваш код ... Не могу ли я привязать свои комбо к объекту свойства моего 'SelectedSchedule'? Должен ли я всегда объявлять новое свойство в моей виртуальной машине для привязки? – andrepaulo

+0

Я предложил некоторые изменения в вашем ответе, так что это должно работать – andrepaulo

+0

Большое вам спасибо за помощь @ d.moncada – andrepaulo