带有绑定未更新的Listview

时间:2013-08-10 14:25:08

标签: c# wpf listview binding

我有一个带有绑定的列表视图,但它没有更新。有人能找到这个bug吗?希望我有一些钱,因为我会提供奖励。

在此屏幕上,当特定恐龙的状态发生变化时,右侧窗口(活动恐龙列表)不会更新(请注意,当您单击恐龙(在本例中为Nancy)时,它会正确显示她的状态是“移动食物”,而“活跃的恐龙名单”则显示她仍在休息:

enter image description here

以下是所有相关代码,从窗口的XAML开始:

<Window x:Class="DinosaurIsland.ActiveDinosaurList"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:DinosaurIsland" 

    Title="ActiveDinosaurList" Height="850" Width="245" WindowStyle="SingleBorderWindow"  Icon="/DinosaurIsland;component/Icon1.ico"  ResizeMode="NoResize"   >
<Window.Resources>
    <local:EnergyBarColorConverter x:Key="EnergyBarColorConverter"/>
    <local:DinoStatusConverter x:Key="DinoStatusConverter"/>


    <DataTemplate x:Key="DinosaurInfo">
        <StackPanel Orientation="Vertical" >
            <Label Name="DinosaurName"  Margin="0,0,0,-8" Content="{Binding Path=PersonalName}"/>
            <Label Name="DinosaurSpecies" Margin="0,0,0,-8" FontStyle="Italic" Content="{Binding Path=Specie}"/>
            <Label Name="DinosaurStatus" Margin="0,0,0,-8" Content="{Binding Path=State, Converter={StaticResource DinoStatusConverter}}"/>
            <Label  HorizontalAlignment="Center" Margin="0,0,0,-2" Content="Energy" />
            <ProgressBar  Name="Health" Margin="0,0,0,10" HorizontalAlignment="Center" VerticalAlignment="Top" Width="160" Height="15"  
                          Foreground ="{Binding Path=Health, Converter={StaticResource EnergyBarColorConverter}}"  Value="{Binding Path=Health}"  />
            <Separator/>
        </StackPanel>
    </DataTemplate>
</Window.Resources>

<Grid Width="210">
    <ListView x:Name="DinoListView"  Width="207" ItemsSource="{Binding Path=Dinosaurs}" HorizontalAlignment="Left" Margin="3,0,0,0">
        <ListView.View>
            <GridView>
                <GridViewColumn Width="180" Header="Select Dinosaur"  CellTemplate="{StaticResource DinosaurInfo}" />
            </GridView>
        </ListView.View>
    </ListView>
</Grid>

这是恐龙课:

using System;
using System.Collections.Generic;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Linq;
using System.Text;

namespace DinosaurIsland 
{
public class Dinosaur : INotifyPropertyChanged
{
    public string _specie;
    public string Specie
        {
        get { return _specie; }
        set{_specie = value; RaisePropertyChanged("Specie");}
        }
    public int Age { get; set; }
    public int Weight { get; set; }
    public double Height { get; set; }
    public int _health;
    public int Health 
        {
        get { return _health; }
        set{_health = value; RaisePropertyChanged("Health");}
        }
    public double Water { get; set; }
    public double FoodConsumed { get; set; }
    public bool Sex { get; set; }
    public string PersonalName { get; set; }
    public System.Windows.Point Head = new System.Windows.Point();
    public List<System.Windows.Point> Location { get; set; }
    public double Length { get; set; }
    public double Speed { get; set; }
    public byte _state;
    public byte State             
        {
        get { return _state; }
        set{_state = value; RaisePropertyChanged("State");}
        }
    public System.Windows.Point Goal = new System.Windows.Point();

    public System.Windows.Point[] FoodLocation = new System.Windows.Point[5]; // The last five locations that the dino found food
    public System.Windows.Point[] WaterLocation = new System.Windows.Point[5]; // The last five locations that the dino found water

    // Constructor
    public Dinosaur()
    {

    }

    public event PropertyChangedEventHandler PropertyChanged;
    //called when a property is changed
    protected void RaisePropertyChanged(string PropertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }
    }
}
}

这是ViewModel类:

using System;
using System.Collections.Generic;
using System.Collections; 
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace DinosaurIsland
{
public class ViewModel : INotifyPropertyChanged
{
    public ViewModel()
    {
       this.Dinosaurs = new ObservableCollection<Dinosaur>();
       for(int i = 0; i < MainWindow.Dinosaurs.Count; i++)

           this.Dinosaurs.Add(new Dinosaur()
        {
            PersonalName = MainWindow.Dinosaurs[i].PersonalName,
            Specie = MainWindow.Dinosaurs[i].Specie,
            Health =  MainWindow.Dinosaurs[i].Health,
            State =  MainWindow.Dinosaurs[i].State
        });
    }

    public event PropertyChangedEventHandler PropertyChanged;
    //called when a property is changed
    public void RaisePropertyChanged(string PropertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }
    }

    private ObservableCollection<Dinosaur> _dinoList = new ObservableCollection<Dinosaur>();
    public ObservableCollection<Dinosaur> Dinosaurs
    {
        get { return _dinoList; }
        set { _dinoList = value; RaisePropertyChanged("Dinosaurs"); }
    }
}

}

以下是调用窗口的方法:

// This is a global        
public ViewModel vm = new ViewModel();

// ....

// Instantiate window
ViewModel vm = new ViewModel();
DinoListDialogBox.DataContext = vm;
DinoListDialogBox.Show();

这应该是拼图的所有部分。我错过了什么?

谢谢...我会在你之后命名一只恐龙。

2 个答案:

答案 0 :(得分:1)

好的看了你的来源可以得到你的用例的解决方案。我确实建议正确检查MVVM。现在看来,正如我在聊天中提到的那样,你的项目在很多方面都违背了MVVM。

将您的当前实现放在一边,以使Dinosaurs列表与ActiveDinosaurList视图同步,这些是我所做的更改:

<强> MainWindow.xaml.cs:

1)将Dinosaurs切换为ObservableCollection<T>和属性。如

public static List<Dinosaur> Dinosaurs = new List<Dinosaur>();

public static ObservableCollection<Dinosaur> Dinosaurs { get; set; }

2)向MainWindow类添加静态构造函数以初始化Dinosaurs属性

static MainWindow() {
  Dinosaurs = new ObservableCollection<Dinosaur>();
}

<强> ViewModel.cs

3)将Dinosaurs属性切换为pass-thru到MainWindow中的静态属性,并删除后备集合。如

private ObservableCollection<Dinosaur> _dinoList = new ObservableCollection<Dinosaur>();
public ObservableCollection<Dinosaur> Dinosaurs
{
   get { return _dinoList; }
   set { _dinoList = value; RaisePropertyChanged("Dinosaurs"); }
}

public ObservableCollection<Dinosaur> Dinosaurs {
  get {
    return MainWindow.Dinosaurs;
  }
}

4)最后添加一个钩子来收听来自CollectionChanged的{​​{1}}上的MainWindow.Dinosaurs以及ViewModel属性RaisePropertyChanged上的Dinosaurs

所以切换:

public ViewModel()
{
   this.Dinosaurs = new ObservableCollection<Dinosaur>();
   for(int i = 0; i < MainWindow.Dinosaurs.Count; i++)
     this.Dinosaurs.Add(new Dinosaur()
      {
         PersonalName = MainWindow.Dinosaurs[i].PersonalName,
         Specie = MainWindow.Dinosaurs[i].Specie,
         Health =  MainWindow.Dinosaurs[i].Health,
         State =  MainWindow.Dinosaurs[i].State
      });
}

public ViewModel() {
  MainWindow.Dinosaurs.CollectionChanged += (sender, args) => RaisePropertyChanged("Dinosaurs");
}

就是这样。现在运行您的模拟,当我转发时间时,我可以看到ActiveDinosaurs列表上的状态更新正常。

答案 1 :(得分:0)

在绑定中使用UpdateSourceTrigger=PropertyChanged

所以你的标签看起来像这样:<Label Name="DinosaurStatus" Margin="0,0,0,-8" Content="{Binding Path=State, Converter={StaticResource DinoStatusConverter} UpdateSourceTrigger=PropertyChanged}" />