1

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

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

在此处输入图像描述

以下是所有相关代码,从窗口的 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();

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

谢谢...我会以你的名字命名一只恐龙。

4

2 回答 2

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>();
}

视图模型.cs

3) 将属性切换Dinosaurs为对静态属性的传递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的属性MainWindow.DinosaursViewModelRaisePropertyChangedDinosaurs

所以切换:

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 列表上的状态更新正常。

于 2013-08-11T23:49:40.810 回答
0

在您的绑定中使用UpdateSourceTrigger=PropertyChanged.

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

于 2013-08-10T20:26:46.147 回答