На основе ваших комментариев я создал минимальный пример, который показывает привязку. Я надеюсь, что это то, что вы искали.
MainWindow.xaml и код позади
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="400" Width="800">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="300*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<DataGrid Grid.Column="0" Grid.Row="0" Width="Auto" ItemsSource="{Binding DeviceList}" SelectedItem="{Binding SelectedDevice}" AutoGenerateColumns="True" />
<DataGrid Grid.Column="1" Grid.Row="0" Width="Auto" DataContext="{Binding SelectedDevice}" ItemsSource="{Binding Path=FaultList}" AutoGenerateColumns="True"/>
<Button Content="Trigger DataGrid 1 update" Grid.Column="0" Grid.Row="1" Margin="10,10,10,10" Width="Auto" Height="Auto" Click="Button_Click"/>
</Grid>
</Window>
// Code behind in MainWindow.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow : Window
{
private MainViewModel vm;
public MainWindow()
{
InitializeComponent();
vm = new MainViewModel();
DataContext = vm;
}
private void Button_Click(object sender, RoutedEventArgs e)
{
vm.AddDevice();
}
}
}
MainViewModel и MainModel
using System;
using System.Collections.ObjectModel;
using System.Linq;
using WpfApp1.ViewModels;
namespace WpfApp1
{
public class MainViewModel : ViewModelBase<MainModel>
{
private DeviceViewModel selectedDevice;
public ObservableCollection<DeviceViewModel> DeviceList
{
get { return Model.DeviceList; }
}
public DeviceViewModel SelectedDevice
{
get { return selectedDevice; }
set
{
selectedDevice = value;
RaisePropertyChanged("SelectedDevice");
}
}
public MainViewModel() : base(new MainModel())
{
}
public void AddDevice()
{
int rnd = new Random().Next(1, 100);
if (!Model.DeviceList.Any(x => x.Name == $"Device_{rnd}"))
Model.DeviceList.Add(new DeviceViewModel($"Device_{rnd}"));
RaisePropertyChanged("DeviceList");
}
}
}
using System.Collections.ObjectModel;
using WpfApp1.ViewModels;
namespace WpfApp1
{
public class MainModel
{
private ObservableCollection<DeviceViewModel> deviceList;
public ObservableCollection<DeviceViewModel> DeviceList
{
get { return deviceList; }
set { deviceList = value; }
}
public MainModel()
{
deviceList = new ObservableCollection<DeviceViewModel>();
}
}
}
DeviceViewModel.cs и Device.cs
using System.Collections.ObjectModel;
using WpfApp1.Models;
namespace WpfApp1.ViewModels
{
public class DeviceViewModel : ViewModelBase<Device>
{
private Fault selectedFault = null;
public string Name
{
get { return Model.Name; }
set
{
Model.Name = value;
RaisePropertyChanged("Name");
}
}
public string SerialNumber
{
get { return Model.Id.ToString(); }
}
public ObservableCollection<FaultViewModel> FaultList
{
get { return Model.FaultList; }
}
public Fault SelectedFault
{
get { return selectedFault; }
set
{
selectedFault = value;
RaisePropertyChanged("SelectedFault");
}
}
public DeviceViewModel() : base(new Device())
{
FaultList.CollectionChanged += FaultList_CollectionChanged;
}
public DeviceViewModel(string name) : this()
{
Name = name;
for (int i = 0; i < 5; i++)
Model.FaultList.Add(new FaultViewModel() { Name = $"Fault_{i} of {name}" });
RaisePropertyChanged("FaultList");
}
private void FaultList_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
RaisePropertyChanged("FaultList");
}
}
}
using System;
using System.Collections.ObjectModel;
namespace WpfApp1.Models
{
public class Device
{
private string name = "";
private Guid id;
private ObservableCollection<FaultViewModel> faultList;
public string Name
{
get { return name; }
set { name = value; }
}
public Guid Id
{
get { return id; }
set { id = value; }
}
public ObservableCollection<FaultViewModel> FaultList
{
get { return faultList; }
set { faultList = value; }
}
public Device()
{
this.id = new Guid();
this.faultList = new ObservableCollection<FaultViewModel>();
}
public Device(string name) : this()
{
this.name = name;
}
}
}
FaultViewModel.cs и Fault.cs
using WpfApp1.Models;
namespace WpfApp1
{
public class FaultViewModel : ViewModelBase<Fault>
{
public string Name
{
get { return Model.FaultName; }
set
{
Model.FaultName = value;
RaisePropertyChanged("Name");
}
}
public string Id
{
get { return Model.FaultId.ToString(); }
}
public FaultViewModel() : base(new Fault())
{
}
}
}
using System;
namespace WpfApp1.Models
{
public class Fault
{
private Guid faultId;
private string faultName;
public Guid FaultId
{
get { return faultId; }
set { faultId = value; }
}
public string FaultName
{
get { return faultName; }
set { faultName = value; }
}
public Fault()
{
this.faultId = new Guid();
}
}
}
Последнее, но не менее важное: ViewModelBase.cs
using System.ComponentModel;
namespace WpfApp1
{
public class ViewModelBase<T> : INotifyPropertyChanged
{
T model;
public T Model { get { return model; } }
public ViewModelBase(T model)
{
this.model = model;
}
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null && !string.IsNullOrEmpty(propertyName))
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Если вы запустите приложение, вы можете нажатькнопка, которая имитирует обновление списка устройств в коде позади. Затем вы можете выбрать устройство, и вторая DataGrid покажет FaultList этого устройства.
Старый ответ
Обновление: Похожиек вашим комментариям и диаграмме классов:
Первое:
Я вижу только один список в классе Device. Я предполагаю, что это источник для первой DataGrid? Таким образом, вы хотите отобразить свойства объектов типа Fault в 1-й DataGrid. Если это так, где находится источник для второй DataGrid? Или вам не хватает свойства Collection в классе Fault?
Second:
Для привязки данных вы должны использовать ObservableCollection , который реализует INotifyCollectionChanged. Вы не можете использовать Список <>.
Третье:
Не видя ваш код, я могу только догадываться, что происходит не так. Давайте предположим, что класс Device содержит ObservableCollection<Fault> FaultList
, а класс Fault содержит ObservableCollection<string> FaultDetails
. DataGrid 1 отображает список неисправностей, и если вы выберете одну из них, DataGrid 2 отображает некоторые подробности неисправностей. В вашей DeviceViewModel у вас будет ObservableCollection<Fault> FaultList
и свойство Fault SelectedFault
. Теперь FaultList должен быть ItemSource первой DataGrid, а SelectedFault должен быть связан со свойством DataGrid.SelectedItem. ItemSource Datagrid 2 должен быть FaultDetails, а DataContext должен быть SelectedFault. Возможно, вам нужно распространять информацию об изменении свойства.
Я не проверял это! Минимальный исполняемый пример, который показывает, что проблема была бы отличной.
Старый ответ:
Прошло много времени с тех пор, как я написал свое последнее приложение WPF, но оновозможно, вы либо инициируете событие NotifyPropertyChanged для 2-й DataGrid в неправильном месте, либо вы вызываете его для неправильного свойства.
DataGrid имеет событие SelectionChanged. Возможно, вы сможете получить доступ к своей виртуальной машине оттуда и вызвать правильное событие PropertyChanged для своей второй DataGrid.