У вашего кода много проблем. Ниже перечислены некоторые из них:
- Свойства привязки должны быть общедоступными, а не частными
- В Коде позади вы пытаетесь установить
Text
ComboBox вместо SelectedValue
- Вы смешиваете код с дизайном ViewModel
Я написал ниже код, который демонстрирует требование с использованием шаблона проектирования MVVM.
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"
xmlns:local="clr-namespace:WpfApp1"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Margin="5" Grid.Column="0">
<Label Content="Year" />
<ComboBox x:Name="txtyr"
ItemsSource="{Binding Years}"
SelectedValue="{Binding Path=years_SelectedValue}" />
</StackPanel>
<StackPanel Margin="5" Grid.Column="1">
<Label Content="Quarter"/>
<ComboBox x:Name="txtqt"
ItemsSource="{Binding Quarters}"
SelectedValue="{Binding Path=quarters_SelectedValue}" />
</StackPanel>
<StackPanel Margin="5" Grid.Column="2">
<Label Content="Name" />
<ComboBox x:Name="txtnm"
ItemsSource="{Binding Names}"
SelectedValue="{Binding Path=names_SelectedValue}" />
</StackPanel>
</Grid>
<DataGrid Grid.Row="1" x:Name="dtGrid" ItemsSource="{Binding Safeties}" SelectedItem="{Binding SelectedSafety}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Year}" Header="Year"/>
<DataGridTextColumn Binding="{Binding Quarter}" Header="Quarter"/>
<DataGridTextColumn Binding="{Binding Name}" Header="Name"/>
<DataGridTextColumn Binding="{Binding SafetyScore}" Header="Safety Score"/>
<DataGridTextColumn Binding="{Binding ID}" Header="ID" Visibility="Collapsed"/>
</DataGrid.Columns>
</DataGrid>
</Grid>
</Window>
Для демонстрации я определил ViewModel в представлении.
MainViewModel.Cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
namespace WpfApp1
{
public class MainWindowViewModel : INotifyPropertyChanged
{
public MainWindowViewModel()
{
var data = Model.GetData();
Safeties.AddRange(data);
Years.AddRange(data.Select(d => d.Year).Distinct());
Quarters.AddRange(data.Select(d => d.Quarter).Distinct());
Names.AddRange(data.Select(d => d.Name).Distinct());
}
private ObservableCollection<int> years = new ObservableCollection<int>();
public ObservableCollection<int> Years
{
get { return years; }
}
private int _years_SelectedValue;
public int years_SelectedValue
{
get { return _years_SelectedValue; }
set
{
_years_SelectedValue = value;
OnPropertyChanged("years_SelectedValue");
}
}
private ObservableCollection<int> quarters = new ObservableCollection<int>();
public ObservableCollection<int> Quarters
{
get { return quarters; }
}
private int _quarters_SelectedValue;
public int quarters_SelectedValue
{
get { return _quarters_SelectedValue; }
set
{
_quarters_SelectedValue = value;
OnPropertyChanged("quarters_SelectedValue");
}
}
private ObservableCollection<string> names = new ObservableCollection<string>();
public ObservableCollection<string> Names
{
get { return names; }
}
private string _names_SelectedValue;
public string names_SelectedValue
{
get { return _names_SelectedValue; }
set
{
_names_SelectedValue = value;
OnPropertyChanged("names_SelectedValue");
}
}
private ObservableCollection<Safety> safeties = new ObservableCollection<Safety>();
public ObservableCollection<Safety> Safeties
{
get { return safeties; }
}
private Safety selectedSafety;
public Safety SelectedSafety
{
get { return selectedSafety; }
set
{
selectedSafety = value;
this.OnPropertyChanged(nameof(SelectedSafety));
if (this.selectedSafety != null)
{
this.years_SelectedValue = selectedSafety.Year;
this.quarters_SelectedValue = selectedSafety.Quarter;
this.names_SelectedValue = selectedSafety.Name;
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
С учетом включения кода вышеНиже показано, как работает эта функция:
Дополнительный код
Для демонстрации яМы создали класс для получения данных
public static class Model
{
public static List<Safety> GetData()
{
return new List<Safety>()
{
new Safety() { ID = 1, Name = "First", Quarter = 1, SafetyScore = 1, Year = 2001 },
new Safety() { ID = 2, Name = "Second", Quarter = 2, SafetyScore = 1, Year = 2001 },
new Safety() { ID = 3, Name = "Third", Quarter = 3, SafetyScore = 1, Year = 2001 },
new Safety() { ID = 4, Name = "Fourth", Quarter = 4, SafetyScore = 1, Year = 2001 },
new Safety() { ID = 5, Name = "First", Quarter = 1, SafetyScore = 1, Year = 2002 },
new Safety() { ID = 6, Name = "Second", Quarter = 2, SafetyScore = 1, Year = 2002 },
new Safety() { ID = 7, Name = "Third", Quarter = 3, SafetyScore = 1, Year = 2002 },
new Safety() { ID = 8, Name = "Fourth", Quarter = 4, SafetyScore = 1, Year = 2002 },
};
}
}
и расширения для AddRange для ObservableCollection
. Однако вы можете использовать ObservableRangeCollection, представленную в C # 7.0
public static class ObservableCollectionExtensions
{
public static void AddRange<T>(this ObservableCollection<T> observableCollection, IEnumerable<T> data)
{
foreach (T item in data)
{
observableCollection.Add(item);
}
}
}
Safety.cs
public class Safety : INotifyPropertyChanged
{
private int id;
public int ID
{
get
{
return id;
}
set
{
id = value;
this.RaisePropertyChange(nameof(ID));
}
}
private int year;
public int Year
{
get
{
return year;
}
set
{
year = value;
this.RaisePropertyChange(nameof(ID));
}
}
private int quarter;
public int Quarter
{
get
{
return quarter;
}
set
{
quarter = value;
this.RaisePropertyChange(nameof(ID));
}
}
private string name;
public string Name
{
get
{
return name;
}
set
{
name = value;
this.RaisePropertyChange(nameof(ID));
}
}
private int safetyScore;
public int SafetyScore
{
get
{
return safetyScore;
}
set
{
safetyScore = value;
this.RaisePropertyChange(nameof(ID));
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChange(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}