如何在wpf中使listview更新?

时间:2009-07-15 14:58:29

标签: wpf data-binding listview

我意识到这是一个很长的问题,但我发现这里没有别的办法,只能发布我的代码,为了清晰起见,我尽量保持简短。当然,违反了大量的最佳实践,这个例子足够长,因为它是......

我制作了一个非常简单的wpf应用程序

  • 显示屏幕左侧的人员列表(格式:名称和年龄在()之间)
  • 显示屏幕右侧所选人员的所有属性
  • 在右侧,您可以编辑属性并在msgbox中查看整个选择

在以下示例中,我编辑了Bar的年龄。但是,在列表中,年龄不会更新。如果我询问基础集合,它似乎仍然有更新.. 如何知道清单?

以下是截图,代码和XAML

注意:如果图像未显示,请尝试在新选项卡或窗口中打开它。


alt text


namespace ASAPBinding
{
    public class Person
    {
        public string Name { get; set; }
        public int Age { get; set; }

        public override string ToString()
        {
            return String.Format("{0} ({1})",Name,Age);     
        }
    }

}

namespace ASAPBinding
{
    public class Dal
    {
        public ObservableCollection<Person> Persons { get; set; }

        public Dal()
        {
            Persons = new ObservableCollection<Person>();
            Persons.Add(new Person() {Name = "Bar", Age = 25});
            Persons.Add(new Person() {Name = "Foo", Age = 50});
        }

        public void PrintOutCollection()
        {
            MessageBox.Show(
                Persons[0].ToString() + "\n" + Persons[1].ToString()
                );
        }
    }
}

<Window x:Class="ASAPBinding.EditPersons"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:ASAPBinding"
     x:Name="window1"
    Title="EditPersons" Height="300" Width="300">
    <Window.Resources>
        <local:Dal x:Key="dal"/>
    </Window.Resources>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*" />
            <ColumnDefinition Width="1*" />
        </Grid.ColumnDefinitions>

        <ListBox Name="ListBox1" 
                 ItemsSource="{Binding Source={StaticResource dal}, Path=Persons, Mode=TwoWay}" 
                 Grid.Column="0"/>
        <StackPanel 
            DataContext="{Binding ElementName=ListBox1, Path=SelectedItem, Mode=TwoWay}"
            Grid.Column="1" Margin="0,0,0,108">

            <TextBox Text="{Binding Path=Name}" />
            <TextBox Text="{Binding Path=Age}"  />
            <Button Click="Button_Click">Show Collection</Button>
        </StackPanel>
    </Grid>
</Window>

public partial class EditPersons : Window
    {
        public EditPersons()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Dal dal = (Dal) window1.FindResource("dal");
            dal.PrintOutCollection();
        }
    }

3 个答案:

答案 0 :(得分:5)

拥有ObservableCollection是不够的,如果要更新特定属性的绑定,您的Person类型必须实现INotifyPropertyChanged

修改

我刚注意到,您的左侧ListBox未更新,因为您没有为Person对象设置DataTemplate。你现在拥有的是一个ToString()实现,它一旦报告给UI就不会得到更新。

你需要这样的东西:

<DataTemplate DataType="{x:Type local:Person}">
   <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding Name}"/>
        <TextBlock Text="("/>
        <TextBlock Text="{Binding Age}"/>
        <TextBlock Text=")"/>
    </StackPanel>
</DataTemplate>

答案 1 :(得分:2)

首先,在收集级别,您ItemsSource的{​​{1}}应为ListView

ObservableCollection

这将通知ObservableCollection<Person> Persons = new ObservableCollection<Person>(); 项目的顺序已更改。

其次,在项目级别。您ListView也应该按照官方documenthere中的说明实施Person界面。

这将告诉INotifyPropertyChanged项目的内容已被更改。

实施ListView时,

INotifyPropertyChanged

已定义,必须在属性设置器中名为显式。 需要注意的一点是,您不需要对属性名称进行硬编码,public event PropertyChangedEventHandler PropertyChanged; 属性可用于自动获取调用者的名称。

CallerMemberName

答案 2 :(得分:1)

示例:

public class Person : DependencyObject
{
    public static readonly DependencyProperty NameProperty = DependencyProperty.Register(
        "Name",
        typeof(string),
        typeof(Person)
    );

    public static readonly DependencyProperty AgeProperty = DependencyProperty.Register(
        "Age",
        typeof(int),
        typeof(Person)
    );

    public string Name
    {
        get { return (string)GetValue(NameProperty); }
        set { SetValue(NameProperty, value); }
    }

    public int Age
    {
        get { return (int)GetValue(AgeProperty ); }
        set { SetValue(AgeProperty , value); }
    }

    public override string ToString()
    {
            return String.Format("{0} ({1})",Name,Age);     
    }
}