WPF ListBox绑定每行只产生一个字符

3
我正在努力理解数据绑定和wpf。我有一个非常简单的程序,其中包含一个对象的ObservableCollection,该对象只包含一个属性——字符串。运行时,它将列表框显示为每行一个字符,并且仅显示第一项。
这一定很简单,但是我被卡住了。如果我删除'binding.Path = ...',那么它将在每一行上显示“expOne.FNode”(三次)。
谢谢!
以下是代码: MainWindow.xaml.cs:
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace expOne
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
    ObservableCollection<FNode> MyFileList = new ObservableCollection<FNode>();
    public MainWindow()
    {
        MyFileList.Add ( new FNode ( "alpha" ) );
        MyFileList.Add ( new FNode ( "bravo" ) );
        MyFileList.Add ( new FNode ( "charlie" ) );
        InitializeComponent();
        Binding binding = new Binding();
        binding.Source = MyFileList;
        binding.Path = new PropertyPath ( "Name" );
        mylistbox.SetBinding ( ListBox.ItemsSourceProperty, binding );
    }
}
}

FNode.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace expOne
{
public class FNode
{
    private string m_name;

    public string Name
    {
        get { return ( m_name ); }
        set { m_name = value; }
    }

    public FNode ( string n )
    {
        m_name = n;
    }

    public FNode()
    {
        m_name = "Bob";
    }
}
}

MainWindow.xaml:

<Window x:Class="expOne.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox Name="mylistbox" HorizontalAlignment="Stretch" FontSize="15" >
            <!--<ListBoxItem Content="First or Last" />-->
        </ListBox> 
    </Grid>
</Window>
2个回答

4
那是因为您将“Name”属性绑定到了Listbox的ItemsSource上,实际上是告诉Listbox绑定字符串中的字符。Listbox绑定Source和Path属性的组合。
要将Listbox绑定到列表,请设置Source。要显示名称,请将ListBox的DisplayMemberPath属性设置为“Name”。
实际上,声明性绑定要简单得多。您可以将列表设置为Listbox的DataContext,例如:
ObservableCollection<FNode> MyFileList = new ObservableCollection<FNode>();
public MainWindow()
{
    MyFileList.Add ( new FNode ( "alpha" ) );
    MyFileList.Add ( new FNode ( "bravo" ) );
    MyFileList.Add ( new FNode ( "charlie" ) );
    InitializeComponent();
    mylistbox.DataContext=MyFileList;
}

然后在XAML中设置绑定:

<ListBox Name="mylistbox" ItemsSource="{Binding}" DisplayMemberPath="Name" />

数据绑定允许您完全将数据与窗口分离。实际上,MVVM风格规定您的演示数据(ViewModel)应该是窗口(View)的单独类。这样,您可以将不同的数据类绑定到同一视图,或将不同的视图绑定到同一对象。
假设您创建了一个名为“ MyProjectViewModel”的类,其中包含“ Name”和“ Files”属性,您可以编写以下代码:
public MyProjectViewModel TheProject {get;set;}
public MainWindow()
{
    TheProject=new MyProject();

    InitializeComponent();
    this.DataContext=TheProject;
}

然后将您需要的任何元素绑定到此ViewModel的属性上,例如:

<TextBox Name="projectName" Text="{Binding Name}" />
<ListBox Name="projectFiles" ItemsSource="{Binding Files}" 
                             DisplayMemberPath="Name" />

如果我省略了绑定语句 binding.Path = new PropertyPath("Name");,那么列表框中将包含三行"expOne.FNode",这是命名空间+类型名称... - Billy Pilgrim
你添加了 "DisplayMemberPath" 吗? - Panagiotis Kanavos
哦,不...我该设置成什么?抱歉我这么蠢。 - Billy Pilgrim

2
不需要在绑定上设置路径,只需为绑定设置源。删除此内容:
binding.Path = new PropertyPath ( "Name" );

或者

只需省略绑定,直接在listBox上设置ItemsSource:

MyFileList.Add(new FNode("alpha"));
MyFileList.Add(new FNode("bravo"));
MyFileList.Add(new FNode("charlie"));
InitializeComponent();
mylistbox.ItemsSource = MyFileList;

DisplayMemberPath 设置为 Name,否则 ListBox 将调用你的类 FNode 的 ToString() 方法并打印完全限定名称,这就是为什么你会看到 expOne.FNode 被打印三次。

<ListBox Name="mylistbox" HorizontalAlignment="Stretch"
         FontSize="15" DisplayMemberPath="Name"/>

谢谢!(感谢你们两个)。“DisplayMemberPath”和“binding.Path”有什么不同?绑定路径何时使用? - Billy Pilgrim
Path是绑定类上的属性,而DisplayMemberPathItemsControl的属性。当您指定路径时,实际上是告诉绑定引擎将ItemsSource设置为该路径中的绑定。而使用DisplayMemberPath则是告诉绑定引擎在底层ItemSource中绑定属性。 - Rohit Vats

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