使用数据绑定使WPF Listview显示ObservableCollection<T>。

7
我可以帮您翻译成中文,内容涉及编程。请注意保留HTML标签,不做解释,只需翻译。以下是需要翻译的内容:

我有一个Project类型的可观察集合,我想在ListView中显示它,但是我的ListView没有显示任何内容,这让我非常困惑。

我的MainWindow.xaml

            <ListView Name="ListViewProjects" Grid.Column="0" Grid.RowSpan="3" SelectionChanged="ListViewProjectsSelectionChanged" ItemsSource="{Binding}" IsSynchronizedWithCurrentItem="True" MinWidth="100">
            <ListView.ItemTemplate>
                <DataTemplate>
                    <WrapPanel>
                        <TextBlock Text="{Binding Path=ProjectID}"/>
                        <TextBlock Text="{Binding Path=ProjectName}"/>
                    </WrapPanel>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>

我的MainWindow.cs

    public partial class MainWindow : Window
{
    ObservableCollection<Project> Projects = new ObservableCollection<Project>();
    ObservableCollection<Employee> Employees = new ObservableCollection<Employee>();

    public MainWindow()
    {
        InitializeComponent();

        DataContext = Projects;

        Project pro1 = new Project(1, "Swordfish");
        Projects.Add(pro1);
        Employee empMads = new Employee("Mads", 1);
        Employee empBrian = new Employee("Brian", 2);
        Employees.Add(empMads);
        Employees.Add(empBrian);
    }

    private void ListViewProjectsSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    }
}

而我的 Project.cs 则是类文件

[Serializable]
class Project : INotifyPropertyChanged
{
    public Project(int id, string name)
    {
        ID = id;
        Name = name;
    }

    private int id;
    public int ID
    {
        get { return id; }
        set
        {
            id = value;
            NotifyPropertyChanged("ProjectID");
        }
    }

    private string name;
    public string Name
    {
        get { return name; }
        set
        {
            name = value;
            NotifyPropertyChanged("ProjectName");
        }
    }

    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    private void NotifyPropertyChanged(String info)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
        }
    }
}

但是我的列表中没有添加任何内容,我看不出来缺少什么才能使它工作。

我将其设置为可观察集合 我设置DataContext为该集合 并在xaml文件中进行绑定

编辑代码部分1:

        public ObservableCollection<Project> Projects { get; set; }
    public ObservableCollection<Employee> Employees { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        Projects = new ObservableCollection<Project>();
        Employees = new ObservableCollection<Employee>();

        DataContext = Projects;

你能否分享一下你是如何设置DataContext的呢? - Josh
4个回答

4

你遇到了绑定路径的问题,因为你使用了类似于ProjectID的绑定路径,但是你的Project类却有一个ID属性。同样的问题也出现在ProjectNameName属性上。

当你在绑定方面遇到了问题时,非常有用的方法是查看Visual Studio调试模式下的Output选项卡,以查看数据绑定引擎返回了哪些错误。这些异常通常不会向用户返回,但是你可以在那里检查它们。


那个可行,但当写错时,我不能在输出或错误列表中看到任何内容。顺便问一下,是否可能让我在同一个XAML文档中具有的ComboBox数据绑定到另一个列表? - Mech0z
System.Windows.Data错误: 40 :绑定表达式路径错误:在'对象''Project' (HashCode=41717140)'上未找到'ProjectID'属性。 BindingExpression: Path = ProjectID; DataItem ='Project' (HashCode = 41717140); 目标元素为'TextBlock' (Name = ''); 目标属性为'Text' (类型为'String')-这是我在开始你的代码时发现的输出窗口中的消息。 是的,可以在运行时更改数据源(我想这就是您要求的),但是这里我没有足够的空间。 我相信您可以在网上找到如何做到这一点的方法。 - Jarek
很有用,因为我不知道VS会输出数据绑定错误。这将大大减少我的XAML/WPF调试时间,谢谢! - Psytronic
我没有看到那些错误,不确定为什么我的代码没有输出。 - Mech0z
在“输出”窗口的下拉菜单中,“显示输出来自:”你选择了什么?应该选择调试。如果设置为构建,则选择调试。希望它能起作用。 - Jarek
这就是它:S 不确定之前我做了什么,因为它没有显示出来,但谢谢,这非常有用。 - Mech0z

3

正如指出的那样,这里有一些问题。作为新的WPF开发人员,其中一个“坑”是你不能使用成员变量,必须使用公共属性:

public ObservableCollection<Project> Projects { get; set; }
public ObservableCollection<Employee> Employees { get; set; }

当然,这些需要在你的构造函数中初始化。

一旦你这样做了,你需要确保集合的属性与你在ListView上绑定的内容匹配。


也许我错了,但是你可以使用私有字段作为数据上下文(这就是Mech0z正在做的),一切都可以正常工作。 - Jarek
谢谢,一旦我将我的公共字段转换为属性,绑定就开始工作了。 - mleise

1

默认情况下,您的成员变量将是私有的。如果您发布的内容是您实际的代码,则XAML无法访问它。请将这些属性设置为公共:

public ObservableCollection<Project> Projects = new ObservableCollection<Project>();
public ObservableCollection<Employee> Employees = new ObservableCollection<Employee>();

实例字段默认为私有。如果您查看他的代码,他省略了任何作用域修饰符,这使它们变成了私有的。 - Josh
我的意思是你写的是公共字段,据我所知,绑定需要公共属性。 - H.B.
如果不想使用DataContext,我不知道该如何完成这个任务。那么,需要更改哪些部分呢? - Mech0z
@Mech0z:或者你可以使用ElementName、RelativeSource或Source来设置一个与数据上下文无关的绑定路径。例如,要绑定到在窗口代码后台声明的属性,你可以给窗口命名,并像这样进行绑定{Binding ElementName=MyWindow, Path=MyProperty}。 - H.B.
2
当然可以,你只需要使用两个具有不同路径的绑定(这也是为什么你不应该将窗口的DataContext设置为其属性之一这么具体的东西,而是通过“DataContext = this;”将其设置为自身,然后绑定就是{Binding Projects}和{Binding Employees})。 - H.B.
显示剩余4条评论

0

1. 你的列表需要是一个公共属性(除非你像你所做的那样设置了DataContext...)(public ObservableCollection<Project> Projects {get;})

2. 你的通知应该与实际属性名称相同:

private int id;
public int ID
{
    get { return id; }
    set
    {
        id = value;
        NotifyPropertyChanged("ID");
    }
}

3. 绑定也需要这样:

<TextBlock Text="{Binding Path=ID}"/>

我认为...


如果我将它们作为属性进行设置,就像您在我添加到主要问题中的“代码编辑1”中所看到的那样,并注释掉Datacontext = Projects,那么什么也不会添加,那么我需要更改我的listview中的绑定,但应该是什么? - Mech0z
如果你的窗口在Xaml中被命名为MyWindow,那么你可以使用ItemsSource="{Binding ElementName=MyWindow, Path=Projects}"进行绑定。 - H.B.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接