C# WPF MVVM创建多个数据网格并将项绑定到它们
我在WPF绑定中遇到了以下问题。 我需要从XML文件中加载对象,并在listbox中创建已加载项的列表,当选择listbox项时,显示合适的对象集 我可以用“代码隐藏”的方式来做,但我真的希望用正确的MVVM方式来做。 My Matrix类由xsd2code生成,其中包含:C# WPF MVVM创建多个数据网格并将项绑定到它们,c#,wpf,mvvm,binding,C#,Wpf,Mvvm,Binding,我在WPF绑定中遇到了以下问题。 我需要从XML文件中加载对象,并在listbox中创建已加载项的列表,当选择listbox项时,显示合适的对象集 我可以用“代码隐藏”的方式来做,但我真的希望用正确的MVVM方式来做。 My Matrix类由xsd2code生成,其中包含: List<CorrectionMatrixType> correctionMatrixField; 我如何通过Viewmodel用三个数据网格“动态”创建类似网格的东西,并将每个矩阵(A、B、C)绑定到它们上,
List<CorrectionMatrixType> correctionMatrixField;
我如何通过Viewmodel用三个数据网格“动态”创建类似网格的东西,并将每个矩阵(A、B、C)绑定到它们上,哪些内容将根据在列表框中选择的值而改变?我知道要将MatrixType绑定到DataGrid,我必须使用ValueConverter将对象转换为二维数组
也许我必须承认我使用的是MVVM灯
有什么建议吗?我会使用INotifyPropertyChanged接口。这里有一个小例子(不完全是你的情况,但足以说明原理,我认为): MatrixType类:
public class MatrixType
{
public string Name { get; set; }
public string Width { get; set; }
public string Height { get; set; }
}
Xaml:
MainViewModel.cs:
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
var list = new List<MatrixType>
{
new MatrixType {Height = "233", Name = "A", Width = "133"},
new MatrixType {Height = "333", Name = "B", Width = "233"},
new MatrixType {Height = "433", Name = "C", Width = "333"}
};
Items = new ObservableCollection<MatrixType>(list);
}
private MatrixType _selectedItem;
public MatrixType SelectedItem
{
get => _selectedItem;
set { _selectedItem = value; OnPropertyChanged(); }
}
public ObservableCollection<MatrixType> Items { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public类主视图模型:INotifyPropertyChanged
{
公共主视图模型()
{
变量列表=新列表
{
新矩阵类型{Height=“233”,Name=“A”,Width=“133”},
新矩阵类型{Height=“333”,Name=“B”,Width=“233”},
新矩阵类型{Height=“433”,Name=“C”,Width=“333”}
};
项目=新的可观察收集(列表);
}
私有矩阵类型_selectedItem;
公共矩阵类型SelectedItem
{
get=>\u选择编辑项;
设置{u selectedItem=value;OnPropertyChanged();}
}
公共ObservableCollection项{get;set;}
公共事件属性更改事件处理程序属性更改;
[NotifyPropertyChangedInvocator]
受保护的虚拟void OnPropertyChanged([CallerMemberName]字符串propertyName=null)
{
PropertyChanged?.Invoke(这是新的PropertyChangedEventArgs(propertyName));
}
}
MainViewModel.cs(使用MVVM灯时):
public类主视图模型:observeObject
{
公共主视图模型()
{
变量列表=新列表
{
新矩阵类型{Height=“233”,Name=“A”,Width=“133”},
新矩阵类型{Height=“333”,Name=“B”,Width=“233”},
新矩阵类型{Height=“433”,Name=“C”,Width=“333”}
};
项目=新的可观察收集(列表);
}
私有矩阵类型_selectedItem;
公共矩阵类型SelectedItem
{
get=>\u选择编辑项;
设置{u selectedItem=value;RaisePropertyChanged();}
}
公共ObservableCollection项{get;set;}
}
我自己写的解决方案,我不知道它是否是好的MVVM解决方案。
我重新编写了XSD,因此MatrixType成为SimpleMatrix,现在:
XAML:
这一切是如何运作的:
这是完整的,我自己的解决方案,对我有效。我希望它能帮助其他人你也能展示一下
MatrixType
类吗?它生成的代码:当他要求MVVM解决方案时,为什么代码隐藏?当您将代码放在viewmodel中而不是放在代码后面时,最好您是对的。我想如果没有viewmodel文件,理解绑定概念会更容易。嗯,我不知道该怎么回答你的问题。它不包含我的两个问题。我甚至不必实现INotifyPropertyChanged,因为我使用的是MVVM灯光。在底部添加了一个新的MainViewModel.cs,用于MVVM灯光
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="100"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0" ItemsSource="{Binding Items}" DisplayMemberPath="Name" SelectedItem="{Binding SelectedItem}"></ListBox>
<Grid Grid.Column="1">
<StackPanel Orientation="Vertical">
<TextBox Text="{Binding SelectedItem.Name}" Height="30"/>
<TextBox Text="{Binding SelectedItem.Height}" Height="30"/>
<TextBox Text="{Binding SelectedItem.Width}" Height="30"/>
</StackPanel>
</Grid>
</Grid>
public class MainViewModel : INotifyPropertyChanged
{
public MainViewModel()
{
var list = new List<MatrixType>
{
new MatrixType {Height = "233", Name = "A", Width = "133"},
new MatrixType {Height = "333", Name = "B", Width = "233"},
new MatrixType {Height = "433", Name = "C", Width = "333"}
};
Items = new ObservableCollection<MatrixType>(list);
}
private MatrixType _selectedItem;
public MatrixType SelectedItem
{
get => _selectedItem;
set { _selectedItem = value; OnPropertyChanged(); }
}
public ObservableCollection<MatrixType> Items { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class MainViewModel : ObservableObject
{
public MainViewModel()
{
var list = new List<MatrixType>
{
new MatrixType {Height = "233", Name = "A", Width = "133"},
new MatrixType {Height = "333", Name = "B", Width = "233"},
new MatrixType {Height = "433", Name = "C", Width = "333"}
};
Items = new ObservableCollection<MatrixType>(list);
}
private MatrixType _selectedItem;
public MatrixType SelectedItem
{
get => _selectedItem;
set { _selectedItem = value; RaisePropertyChanged(); }
}
public ObservableCollection<MatrixType> Items { get; set; }
}
<ListBox Margin="5,20,0,5" ItemsSource="{Binding CorrectionMatrixes}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<command:EventToCommand Command="{Binding SelectionChangedCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
<i:EventTrigger EventName="Loaded">
<command:EventToCommand Command="{Binding ListBoxLoadedCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
<DataGrid CanUserAddRows="False" HeadersVisibility="None" ItemsSource="{Binding CorrectionMatrixA, Converter={StaticResource MatrixToArray }}"/>
public RelayCommand<SelectionChangedEventArgs> SelectionChangedCommand => new RelayCommand<SelectionChangedEventArgs>(SelectionChanged);
public RelayCommand<RoutedEventArgs> ListBoxLoadedCommand => new RelayCommand<RoutedEventArgs>(ListBoxLoaded);
private string CorrectionMatrixName { get; set; }
private void ListBoxLoaded(RoutedEventArgs obj)
{
if (obj.Source is ListBox listBox)
{
listBox.SelectedIndex = 0;
}
}
private void SelectionChanged(SelectionChangedEventArgs obj)
{
if (obj.AddedItems.Count <= 0) return;
if (obj.AddedItems[0] is CorrectionMatrix matrix)
{
CorrectionMatrixName = matrix.name;
}
RaisePropertyChanged(() => CorrectionMatrixA);
}
public SimpleMatrix CorrectionMatrixA
{
get
{
try
{
var x = Matrixes.Correction.Where(a => a.name == CorrectionMatrixName)
.Select(a => a.A).Single();
return x;
}
catch (InvalidOperationException)
{
return null;
}
}
}
Matrixes = settingsLoader.LoadMatrixes(Properties.Resources.MatrixesSettings);