ObservableCollection被更改后,ListView没有更新

5
我有一个ListView,当我得到数据时,我会立即更新它。如果我在ViewModel的构造函数中向ObservableCollection添加项目,则ListView将得到更新,但是如果我在某个方法中添加项目,则不会更新。
我在Stackoverflow上花费了很多时间,我知道有许多相关的问题,但我找不到答案。令我困扰的是,如果在构造函数中添加值可以正常工作,那么为什么在某些方法中添加值就无法工作。
以下是我的一些细节:
- 我正在使用ObservableCollection - 设置DataContext - 在XAML中将ObservableCollection绑定到ListView
以下是XAML代码:
<UserControl x:Class="WFP_Illustrated.UserControls.WeatherForcastControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="300" d:DesignWidth="300"
         >
<UserControl.Resources>
    <Style TargetType="TextBlock" x:Key="TextStyle">
        <Setter Property="FontFamily" Value="Adobe Caslon Pro"/>
        <Setter Property="FontSize" Value="18"/>
        <Setter Property="MinWidth" Value="60"/>
    </Style>
    <DataTemplate x:Key="ForcastTemplate">
        <Border BorderBrush="Aqua" BorderThickness="1" Padding="5" Margin="5">
            <Grid>
                <Grid.RowDefinitions>
                    <RowDefinition/>
                    <RowDefinition/>
                    <RowDefinition/>
                </Grid.RowDefinitions>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition/>
                    <ColumnDefinition/>
                </Grid.ColumnDefinitions>

                <TextBlock Grid.Row="0" Grid.ColumnSpan="2" Text="{Binding Path= Day}" Style="{StaticResource TextStyle}"/>
                <TextBlock Grid.Row="1" Grid.Column="0" Text="{Binding Path= Condition}"   Style="{StaticResource TextStyle}"/>
                <Image Grid.Row="1" Grid.Column="1" />
                <TextBlock Grid.Row="2" Grid.Column="0" Text="{Binding Path= Low}"  Style="{StaticResource TextStyle}"/>
                <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path= High}"  Style="{StaticResource TextStyle}"/>
            </Grid>
        </Border>
    </DataTemplate>
</UserControl.Resources>
<Grid>
    <ListView Name="ForcastList"
             ItemTemplate="{StaticResource ForcastTemplate}"
             ItemsSource="{Binding ForcastList}"
             Background="SlateGray"
             >

    </ListView>
</Grid>

XAML CodeBehind

public partial class WeatherForcastControl : UserControl
{
    private WeatherForcastViewModel _viewModel;
    public WeatherForcastControl()
    {
        InitializeComponent();
        _viewModel = new WeatherForcastViewModel();
        this.DataContext = _viewModel;
    }
}

这里是ModelView代码

  private ObservableCollection<ForcastInfo> _forcastList;
    public ObservableCollection<ForcastInfo> ForcastList
    {
        get { return _forcastList; }
        //set
        //{
        //    _forcastList = value;
        //    OnPropertyChanged("ForcastList");
        //}
    }

    public WeatherForcastViewModel()
    {
        //If this is uncommented , I will see values in ListView
        //ForcastInfo forcast = new ForcastInfo();
        //forcast.Condition = "clear";
        //forcast.Day = "Sunday";
        //forcast.High = "70";
        //forcast.Low = "50";
        //_forcastList = new ObservableCollection<ForcastInfo>();
        //ForcastList.Add(forcast);
        //ForcastList.Add(forcast);
        //ForcastList.Add(forcast);
        //ForcastList.Add(forcast);
        //ForcastList.Add(forcast);
        //ForcastList.Add(forcast);

        //Callback from MainView ,forcast data is available
        Messenger.Default.Register<GoToForcast>
       (
            this, (action) => MessageFromMain(action)
       );
    }

    private void MessageFromMain(GoToForcast message)
    {
        //This should work but its not working
        ForcastInfo forcast = new ForcastInfo();
        forcast.Condition = "clear";
        forcast.Day = "Sunday";
        forcast.High = "70";
        forcast.Low = "50";
        _forcastList = new ObservableCollection<ForcastInfo>();
        ForcastList.Add(forcast);
        ForcastList.Add(forcast);
        ForcastList.Add(forcast);
        ForcastList.Add(forcast);
        ForcastList.Add(forcast);
        ForcastList.Add(forcast);

        //ForcastList = message.ForcastList;
    }

1
MessageFromMain 是做什么的? - Ritch Melton
我正在使用MVVM Light,当我有预测条件可用时,MessageFromMain将被调用。在此函数中,我只是将从回调获取的forcastList分配给此ViewModel的属性。请参见注释代码。 - sachin saner
啊,我现在明白了,你是在更新时替换集合。 - Ritch Melton
2个回答

5
问题在于你将_forecastList设置为ObservableCollection的一个新实例。只需这样做:
public WeatherForcastViewModel()
{

    _forcastList = new ObservableCollection<ForcastInfo>();
    //Callback from MainView ,forcast data is available
    Messenger.Default.Register<GoToForcast>
   (
        this, (action) => MessageFromMain(action)
   );
}


private void MessageFromMain(GoToForcast message)
{
    //This should work but its not working
    ForcastInfo forcast = new ForcastInfo();
    forcast.Condition = "clear";
    forcast.Day = "Sunday";
    forcast.High = "70";
    forcast.Low = "50";
    //_forcastList = new ObservableCollection<ForcastInfo>(); <---- this is messing you up
    ForcastList.Add(forcast);
    ForcastList.Add(forcast);
    ForcastList.Add(forcast);
    ForcastList.Add(forcast);
    ForcastList.Add(forcast);
    ForcastList.Add(forcast);

    //ForcastList = message.ForcastList;
}

谢谢,伙计,我现在感觉好蠢啊!!哈哈,而且我花了一段时间才接受答案,因为我犯了以下错误:私有无返回值方法 MessageFromMain(GoToForcast message) {//花了很长时间才接受答案,因为我做了这个// ForcastList = message.ForcastList;//而不是这样做foreach (ForcastInfo f in message.ForcastList) { ForcastList.Add(f); } } - sachin saner

2

你改变了列表属性引用的对象,但在该方法中未通知视图。要么仅使用属性并在setter中注释通知,或者使其不可能更改引用,后者通常是最佳方法:

Well, you change the object the list property references and do not tell the view about it by setting the field to a new collection in that method.

要么仅使用属性并在setter中注释通知,或者使其不可能更改引用,后者通常是最佳方法:

private readonly ObservableCollection<ForcastInfo> _forcastList = new ObservableCollection<ForcastInfo>();
public ObservableCollection<ForcastInfo> ForcastList
{
    get { return _forcastList; }
}

现在你无法搞乱绑定,因为该属性始终指向同一个对象。如果要使用此设置替换列表,请对其调用 Clear() 并添加新对象。


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