我在WPF绑定中遇到了以下问题。 我需要从XML文件加载对象并在列表框中创建已加载项目的列表,并在选择列表框项目时显示适当的对象集。
我可以用'code behind'风格来做,但我真的想以适当的MVVM方式做到这一点。 My Matrixes类由xsd2code生成,其中包含:
List<CorrectionMatrixType> correctionMatrixField;
并遵循
public partial class CorrectionMatrixType {
public MatrixType A {get; set;}
public MatrixType B {get; set;}
public MatrixType C {get; set;}
... }
我如何通过Viewmodel创建'动态类似Grid的三个DataGrids,并将每个矩阵(A,B,C)绑定到哪个内容将根据列表框中选择的值更改?我知道要将我的MatrixType绑定到DataGrid,我必须使用ValueConverter将我的对象转换为二维数组。
也许我不得不承认我正在使用MVVM Light。
请提出任何建议?
答案 0 :(得分:1)
我会使用INotifyPropertyChanged接口。这是一个小例子(不完全是你的情况,但我认为足以显示原理):
MatrixType类:
public class MatrixType
{
public string Name { get; set; }
public string Width { get; set; }
public string Height { get; set; }
}
的Xaml:
<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>
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));
}
}
MainViewModel.cs(使用MVVM Light时):
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; }
}
答案 1 :(得分:0)
我自己写了解决方案,我不知道它是不是很好的MVVM解决方案。 我重新编写了我的XSD,因此MatrixType变为SimpleMatrix,现在:
XAML:
<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 }}"/>
在我的viewmodel中:
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);
这一切是如何运作的:
加载用户控件时=&gt;列表框上的选定索引设置为零
当列表框中的选定项目发生更改时,会触发更改CorrectionMatrixName的事件
绑定属性返回合适的矩阵,按名称
我不发布转换器代码 - 这里没关系。 多数民众赞成,我自己的解决方案对我有用。我希望它能帮助其他人