【问题标题】:WPF - DataGrid doesn't show listWPF - DataGrid 不显示列表
【发布时间】:2019-08-20 15:31:46
【问题描述】:

我的目标是在数据网格中输出一个列表,但这不起作用并且数据网格是空的。

我尝试以另一种方式显示列表,它确实做到了(但我不记得它是什么)并且它有效,除了它不在数据网格中而只是在数据中。我已经改变了一些东西,但当时它已经到了尽头并被显示出来。

主窗口中的视图模型:

public class ViewModel
        {
            public List<ssearch> Items { get; set; }

            private static ViewModel _instance = new ViewModel();
            public static ViewModel Instance { get { return _instance; } }
        }

        public MainWindow()
        {
            InitializeComponent();
            DataContext = new ViewModel();

            //For simplicity, let's say this window opens right away
            var Mdata = new MDataWindow { DataContext = DataContext };
            Mdata.Show();
        }

其他数据显示窗口:

string searchParam = "status = 1"; 
        public MDataWindow()
        {
            InitializeComponent();
        }

        private void AButton_Click(object sender, RoutedEventArgs e)
        {
            MainWindow.ViewModel.Instance.Items = Search(searchParam);
        }

public List<ssearch> Search(string where)
        {
            {
                 //Lots of stuff going on here
            }
            return returnList;
        }

在 WPF 中:

<Window x:Class="WPFClient.MDataWindow"
        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:WPFClient"
        mc:Ignorable="d"
        Title="MDataWindow" Height="Auto" Width="Auto">
    <StackPanel>
        <Button x:Name="AButton" Click="AButton_Click" Content="Load" />

        <DataGrid ItemsSource="{Binding Items}" />
    </StackPanel>
</Window>

我不知道错误在哪里,并试图在不杀死错误源的情况下尽可能地精简代码。当我按下“加载”按钮时,Datagrid 只是保持空白。

编辑: 在将列表传递给 ViewModel 之前,我尝试将列表转换为 observableColletion,但这不起作用。我正在使用一个库,我不确定如何使用 observableCollection,所以我转换了它而不是立即使用它:

虚拟机: public ObservableCollection&lt;Product&gt; Items { get; set; }

数据窗口:

List<Product> pp = Search_Products(searchParam);
var oc = new ObservableCollection<Product>(pp);
MainWindow.ViewModel.Instance.Items = oc;

【问题讨论】:

  • “我不知道错误在哪里” - 如果有任何绑定错误,那么它们会在输出窗口中列出
  • 使用 ObservableCollection 代替 List
  • 你的虚拟机是否实现了INotifyPropertyChanged?使用 ObservableCollection 而不是列表。检查您的输出窗口是否有任何错误
  • @ASh,不,与绑定错误无关。缺少 2 个 dll,但我认为它们与错误无关。
  • And.. 在 get;set 之后立即将该 observablecollection 初始化为一个新集合,因此它最初不为空。然后 clear() 然后 .add() 到那个,而不是将它设置为一个新的集合。

标签: c# wpf datagrid


【解决方案1】:

首先,将您的List&lt;Product&gt; 更改为ObservableCollection&lt;Product&gt;,因为这将有助于立即显示添加/删除列表中的项目。

这是因为ObservableCollection 实现了INotifyCollectionChanged 接口来通知它绑定到的目标(DataGrid),以更新它的UI。

其次,由于您的集合的引用更改,您的绑定永远无法按预期工作。

private void AButton_Click(object sender, RoutedEventArgs e)
{
    // You are changing your Items' reference completely here, the XAML binding 
    // in your View is still bound to the old reference, that is why you're seeing nothing.
    //MainWindow.ViewModel.Instance.Items = Search(searchParam);

    var searchResults = Search(searchParam);
    foreach(var searchResult in searchResults)
    {
        MainWindow.ViewModel.Instance.Items.Add(searchResult);
    }
}

确保您在运行 Add 循环时已将 List 更改为 ObservableCollection,否则您将收到异常说项目集合状态不一致。

【讨论】:

    【解决方案2】:

    ViewModel 类应实现INotifyPropertyChanged 接口,并在Items 设置为新集合时引发其PropertyChanged 事件:

    public class ViewModel : INotifyPropertyChanged
    {
        private List<ssearch> _items;
        public List<ssearch> Items
        {
            get { return _items; }
            set { _items = value; OnPropertyChanged(); }
        }
    
        private static ViewModel _instance = new ViewModel();
        public static ViewModel Instance { get { return _instance; } }
    
    
        public event PropertyChangedEventHandler PropertyChanged;
        private void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] String propertyName = "")
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    无论项目类型如何,都需要通知视图。

    如果将Items的类型更改为ObservableCollection&lt;T&gt;,则应在视图模型中初始化集合一次

    public class ViewModel
    {
        public ObservableCollection<ssearch> Items { get; } = new ObservableCollection<ssearch>();
    
        private static ViewModel _instance = new ViewModel();
        public static ViewModel Instance { get { return _instance; } }
    }
    

    ...然后将项目添加到此集合中,而不是将属性设置为新的:

    private void AButton_Click(object sender, RoutedEventArgs e)
    {
        MainWindow.ViewModel.Instance.Items.Clear();
        var search = Search(searchParam);
        if (search != null)
            foreach (var x in search)
                MainWindow.ViewModel.Instance.Items.Add(x);
    
    }
    

    【讨论】:

    • 谢谢!到目前为止效果很好,但我只显示标题列。不再是问题的一部分,但你知道我该如何解决这个问题吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-03
    • 2014-08-01
    • 2019-09-02
    • 1970-01-01
    • 2014-02-09
    相关资源
    最近更新 更多