C# WPF MVVM创建多个数据网格并将项绑定到它们

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)绑定到它们上,

我在WPF绑定中遇到了以下问题。 我需要从XML文件中加载对象,并在listbox中创建已加载项的列表,当选择listbox项时,显示合适的对象集

我可以用“代码隐藏”的方式来做,但我真的希望用正确的MVVM方式来做。 My Matrix类由xsd2code生成,其中包含:

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:

这一切是如何运作的:

  • 加载用户控件时=>listbox上的选定索引设置为零

  • 当更改列表框上的选定项时,它将触发更改CorrectionMatrixName的事件

  • 绑定属性返回合适的矩阵,按名称在数组中查找它

  • 我不发布转换器代码-这里没关系。
    这是完整的,我自己的解决方案,对我有效。我希望它能帮助其他人

    你也能展示一下
    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);