Datagrid 不显示来自 ObservableCollection 的 MVVM 中的数据

Posted

技术标签:

【中文标题】Datagrid 不显示来自 ObservableCollection 的 MVVM 中的数据【英文标题】:Datagrid not displaying data in MVVM from ObservableCollection 【发布时间】:2015-05-20 12:33:03 【问题描述】:

我正在使用 MVVM 构建一个基本的 WPF 应用程序。我正在尝试获取有关不同发电厂的数据以显示在 Datagrid 上。该程序构建良好并显示网格线,但没有数据。我看过很多类似的问题并尝试了几件事,但似乎没有任何效果。我想知道这个问题是否只是我不知道要寻找的简单事情。

查看:

public class Plant : INotifyPropertyChanged

    #region Properties

    private int plantID;
    public int PlantID
    
        get  return plantID; 
        set
        
            plantID = value;
            RaisePropertyChanged("PlantID");
        
    

    //...etc for all properties//
    #endregion

    void RaisePropertyChanged(string prop)
    
        if (PropertyChanged != null)  PropertyChanged(this, new PropertyChangedEventArgs(prop)); 
    

    public event PropertyChangedEventHandler PropertyChanged;

视图模型:

public class MainViewModel : ViewModelBase, IPlantViewModel

    private ObservableCollection<Plant> _plants = new ObservableCollection<Plant>();
    private ICommand _loadCommand;

    public MainViewModel()
    
        _plants = GetPlants();
        _plants.Add(new Plant ()PlantID=1, Name="Orange Plant", Address="1111 Orange Road", PlantPhone="(314)456 7489",PlantFax="(593)202 6948", Contact="John Smith");
        _plants.Add(new Plant()  PlantID = 2, Name = "Blue Plant", Address = "2222 Blue Lane", PlantPhone = "6368967483", PlantFax = "783279948", Contact = "Jane Doe" );
    

    public ObservableCollection<Plant> Plants
    
        get  return _plants; 
    

    public ObservableCollection<Plant> GetPlants()
    
        if (_plants == null || _plants.Count == 0)
            _loadCommand.Execute(_plants);

        return _plants;
    

查看:

    <UserControl 
    x:Class="Directory.MVVM.View.DirectoryView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:dg="http://schemas.microsoft.com/wpf/2008/toolkit"
    xmlns:local="clr-namespace:Directory.ViewModel"
    Height="481" Width="708">
<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="21*"/>
        <ColumnDefinition Width="79*"/>
    </Grid.ColumnDefinitions>
    <DataGrid
        ItemsSource="Binding Source=Plants"
        Name="PlantGrid"
        HorizontalAlignment="Left" 
        Margin="82,54,0,0" 
        VerticalAlignment="Top" 
        Height="147" Width="515"
        AutoGenerateColumns="False" Grid.ColumnSpan="2">
        <DataGrid.DataContext>
            <local:MainViewModel />
        </DataGrid.DataContext>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Plant ID" Width="89" Binding="Binding Path=PlantID,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay" />
            <DataGridTextColumn Header="Name" Width="140" Binding="Binding Path=Name,UpdateSourceTrigger=PropertyChanged, Mode=TwoWay " />
            <DataGridTextColumn Header="Address" Width="90"    Binding="Binding Path=Address, UpdateSourceTrigger=PropertyChanged,Mode=TwoWay" />
            <DataGridTextColumn Header="Phone" Width="90" Binding="Binding Path=PlantPhone, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay" />
            <DataGridTextColumn Header="Fax" Width="60" Binding="Binding Path=PlantFax,UpdateSourceTrigger=PropertyChanged,Mode=TwoWay" />
            <DataGridCheckBoxColumn Header="Contact" Width="58" Binding="Binding Path=Contact, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay" />
        </DataGrid.Columns>
    </DataGrid>

视图背后的代码(不确定我是否应该在此处添加更多内容):

public partial class DirectoryView : UserControl

public DirectoryView()

    InitializeComponent();


另外,我以此作为参考:

http://wpfgrid.blogspot.com/2014/02/simple-observablecollection-wpf-mvvm.html

【问题讨论】:

你没有遗漏一些代码吗? Plant 对象只有 PlantID 我还有几个属性,但我只包含了一个来解决问题。关键是,所有的属性都是这样设置的。 我还没有看到任何问题。 如果在代码隐藏中设置数据上下文是否有效?像这样。DataContext=new MainViewModel() 为什么这被否决了,好像 MVVM 很简单。 【参考方案1】:

尝试在您的数据网格中更改您的 itemsource 绑定,您有源而不是路径。来自

ItemsSource="Binding Source=Plants"

ItemsSource="Binding Path=Plants"

ItemsSource="Binding Plants"

更改绑定将解决以下问题:至少对于您在 mainviewmodel 的构造函数中添加的 id 为 1 和 2 的两种植物,您的数据未显示在网格中。您还可以在构造函数中调用 GetPlants,通过在命令上调用 execute 来加载其他植物。我们看不到您如何将植物添加到 observablecollection 中。您可能想看看如何将这些植物添加到 getplants 中的 observablecollection 中。如果注释掉

_plants = GetPlants();

主视图模型

导致您看到两个工厂,您在命令执行方法中添加项目的方式也存在问题。

【讨论】:

这两个选项都删除了我的网格线。解决方案中也没有错误,但会弹出“TargetInvocationException was unhandled”? @Urn_ee 尝试在 MainViewModel 构造函数中删除/调试 GetPlants 方法调用,如果这对 PlantId 属性以外的 Plant 类中的属性不起作用,则您没有它们的代码在这个问题中,所以我不知道他们在做什么。修复绑定错误后,我看到一个网格有两个植物 id 1 和 2。 删除 GetPlants 方法适用于绑定修复。谢谢!【参考方案2】:

如果您像以前一样设置 DataContext,则每次加载新的 UserControl 时,您的数据网格都会获得 MainViewmodel 的新实例。

    <DataGrid.DataContext>
        <local:MainViewModel />
    </DataGrid.DataContext>

所以你必须先将你的 itemssource 更改为

ItemsSource="Binding Path=Plants"

现在您需要检查的是如何“填充”您的收藏。如果您不使用 Add、Clear 和 Remove 来更改您的集合,那么您必须提高 OnPropertyChanged() 以便 WPF 注意到有更改。

public ObservableCollection<Plant> Plants

    get 
    
        return _plants;
    

    set 
    
         _plants = value;
         OnPropertyChanged();
    


【讨论】:

认为您的意思是不设置 - 获取/获取?也不需要公共集。见***.com/questions/17183812/… 是的,我的意思是设置:),是的,当您不使用 Add/Remove Clear 更改集合并将属性设置为新实例时,您只需要 OnPropertyChanged()。 你同意 observablecollection 的一个新实例,如果在命令中加载植物的代码正在执行新的操作,则该集合将被使用,这将解决该问题。【参考方案3】:

我是这样做的:

Window Constructor 实例化视图模型(这里我将它作为属性,但实例化也可以在构造函数内部)并将 DataContext 设置为 ViewModel:

public partial class WinFilesTransmitted : Window

    static FTViewModel w = new FTViewModel();
    public WinFilesTransmitted()
    
        InitializeComponent();
        DataContext = w;
    

DataGrid xaml 然后这样做:

<DataGrid AutoGenerateColumns="False" HorizontalAlignment="Stretch" Margin="0,0,0,0" VerticalAlignment="Stretch"
                        ItemsSource="Binding DataContext.oFTrn, RelativeSource=RelativeSource AncestorType=x:Type Window">
    <DataGrid.Columns>
        <DataGridTextColumn Binding="Binding UID" Header="xID" Width="40"/>
        <DataGridTextColumn Binding="Binding TransID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" Header="TransID" Width="40"/>
        <DataGridTextColumn Binding="Binding DocID, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" Header="DocID" Width="40"/>
        <DataGridTextColumn Binding="Binding TransmittalName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged" Width="325">

所以datagrid的ItemsSource设置为我的observablecollection,列直接绑定属性。

【讨论】:

以上是关于Datagrid 不显示来自 ObservableCollection 的 MVVM 中的数据的主要内容,如果未能解决你的问题,请参考以下文章

显示来自 Observable Object SwiftUI 的列表

Datagrid 显示架构信息而不是实际数据

DataGrid 或 GridView CellTemplate 中的动态内容

easyui1.32 dataGrid显示-隐藏会出现显示不全问题

vb datagrid不显示数据

DataGrid显示不出来