按钮单击后更改ObservableCollection后ListView不更新

时间:2015-02-02 00:56:17

标签: xaml listview windows-phone-8 mvvm-light win-universal-app

我有一个ListView我正在使用RelayCommand按钮点击更新。如果我在ListView的构造函数中向observableCollection添加项目,则ViewModel会更新,但如果我在单击按钮后在方法中执行此操作,则会更新ObservableCollection

我花了很多时间研究StackOverflow,虽然有很多相关的问题我找不到答案。什么在困扰我,我无法理解的是,当我在构造函数中添加值时它会起作用。

我正在使用DataContext

ObservableCollection设置为在页面级别查看模型 在XAML中将ListView绑定到<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:MyFare" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:ViewModel="using:MyFare.ViewModel" x:Class="MyFare.MainPage" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" DataContext="{Binding Main, Mode=OneWay, Source={StaticResource Locator}}"> <Grid Height="640" Margin="0,0.333,0,-0.333" VerticalAlignment="Top"> <TextBlock x:Name="title" Text="View My Fare" Margin="0,10,0,603"/> <TextBox x:Name="txtCurrentValue" InputScope="Number" PlaceholderText="Enter your Current Balance" Margin="0,53,0,0" Text="{Binding CurrentBalance, Mode=TwoWay}"/> <Button Content="Show Fares" HorizontalAlignment="Left" Margin="96,113,0,0" VerticalAlignment="Top" Command="{Binding ShowFaresCommand, Mode=OneWay}" CommandParameter="{Binding CurrentBalance}" /> <ListView x:Name="nbc" SelectionMode="Single" Margin="10,182,10,150" ItemsSource="{Binding Charges}"> <ListView.Resources> <DataTemplate x:Key="FareTemplate"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Text="{Binding AmountToRecharge}" TextAlignment="Right" Grid.ColumnSpan="4" Margin="0,0,-28,0" FontFamily="{StaticResource PhoneFontFamilyNormal}" FontSize="{StaticResource TextStyleLargeFontSize}"></TextBlock> <TextBlock Text="{Binding BonusAmount}" TextAlignment="Right" Margin="118.333,0,-128.333,0" Grid.Column="3" FontSize="{StaticResource TextStyleLargeFontSize}"/> <TextBlock Text="{Binding NewBalance}" TextAlignment="Right" Margin="118,0,-229.333,0" Grid.Column="3" FontSize="{StaticResource TextStyleLargeFontSize}"/> <TextBlock Text="{Binding NumberofRides}" TextAlignment="Right" Margin="298,0,-308.333,0" Grid.Column="3" FontSize="{StaticResource TextStyleLargeFontSize}"/> </Grid> </DataTemplate> <ItemsPanelTemplate x:Key="FaresPanelTemplate"> <VirtualizingStackPanel Orientation="Vertical"></VirtualizingStackPanel> </ItemsPanelTemplate> <DataTemplate x:Key="headerTemplate"> <Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="90" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <TextBlock Text="Amount to Recharge" Grid.Column="0" TextWrapping="WrapWholeWords" FontFamily="{StaticResource PivotHeaderItemFontFamily}" FontSize="{StaticResource ContentControlFontSize}"/> <TextBlock Text="Bonus Amount" Grid.Column="1" TextWrapping="WrapWholeWords" FontFamily="{StaticResource PivotHeaderItemFontFamily}" FontSize="{StaticResource ContentControlFontSize}"/> <TextBlock Text="New Balance" Grid.Column="2" TextWrapping="WrapWholeWords" FontFamily="{StaticResource PivotHeaderItemFontFamily}" FontSize="{StaticResource ContentControlFontSize}"/> <TextBlock Text="Number of Rides" Grid.Column="3" TextWrapping="WrapWholeWords" FontFamily="{StaticResource PivotHeaderItemFontFamily}" FontSize="{StaticResource ContentControlFontSize}"/> </Grid> </DataTemplate> </ListView.Resources> <ListView.HeaderTemplate> <StaticResource ResourceKey="headerTemplate"/> </ListView.HeaderTemplate> <ListView.ItemsPanel> <StaticResource ResourceKey="FaresPanelTemplate"/> </ListView.ItemsPanel> <ListView.ItemTemplate> <StaticResource ResourceKey="FareTemplate"/> </ListView.ItemTemplate> <ListView.DataContext> <ViewModel:MainViewModel/> </ListView.DataContext> </ListView> </Grid>

XAML代码

 using MyFareFare.Library;
 using GalaSoft.MvvmLight;
 using GalaSoft.MvvmLight.Command;
 using System;
 using System.Collections.ObjectModel;
 using System.Windows.Input;

 namespace MyFareFare.ViewModel {
 /// <summary>
 /// This class contains properties that the main View can data bind to.
 /// <para>
 /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
 /// </para>
 /// <para>
 /// You can also use Blend to data bind with the tool's support.
 /// </para>
 /// <para>
 /// See http://www.galasoft.ch/mvvm
 /// </para>
 /// </summary>
 public class MainViewModel : ViewModelBase
 {
     /// <summary>
     /// The <see cref="BonusChargesValue" /> property's name.
     /// </summary>
     public const string ChargesListPropertyName = "ChargeList";

     public const string PageNamePropertyName = "PageName";

     public const string CurrentBalancePropertyName = "CurrentBalance";

     public const string ButtonTextPropertyName = "ButtonText";

     private string _pageName = "My Fare";

     private string _currentBalance = "";

     private string _buttonText = "Show Fares";

     private RelayCommand _showFaresCommand; 

     public ObservableCollection<BonusChargesValue> _charges = null;

     public string PageName
     {
         get
         {
             return _pageName;
         }

         set
         {
             if (_pageName == value)
             {
                 return;
             }

             //  RaisePropertyChanging(ChargesListPropertyName);
             _pageName = value;
             RaisePropertyChanged(PageNamePropertyName);
         }
     }

     public string ButtonText
     {
         get
         {
             return _buttonText;
         }
         set
         {
             if (_buttonText == value)
             {
                 return;
             }

             //  RaisePropertyChanging(ChargesListPropertyName);
             _buttonText = value;
             RaisePropertyChanged(ButtonTextPropertyName);
         }
     }

     public string CurrentBalance
     {
         get
         {
             return _currentBalance;
         }

         set
         {
             if (_currentBalance == value)
             {
                 return;
             }

             //  RaisePropertyChanging(ChargesListPropertyName);
             _currentBalance = value;
             RaisePropertyChanged(CurrentBalancePropertyName);
         }
     }

     /// <summary>
     /// Sets and gets the Charges property.
     /// Changes to that property's value raise the PropertyChanged event. 
     /// </summary>
     public ObservableCollection<BonusChargesValue> Charges
     {
         get
         {
             return _charges;
         }

         set
         {
             if (_charges == value)
             {
                 return;
             }

            // RaisePropertyChanging(ChargesListPropertyName);
             _charges = value;
             RaisePropertyChanged(ChargesListPropertyName);
         }
     }

     public RelayCommand ShowFaresCommand
     {
         get;
         set;
     } 

     //public RelayCommand ShowFaresCommand 
     //{
     //    get
     //    {
     //        return _showFaresCommand
     //          ?? (_showFaresCommand = new RelayCommand(
     //              ()=> 
     //              {
     //                  _charges = new ObservableCollection<BonusChargesValue>();
     //                  CalculateMetroFare cmcf = new CalculateMetroFare();
     //                  if (!string.IsNullOrWhiteSpace(CurrentBalance))
     //                  {
     //                      _charges = cmcf.Add2ExistingCard(Convert.ToInt32(CurrentBalance));
     //                  }

     //              }));

     //    }  
     //}

    // public RelayCommand ShowFares { get; set; }

     /// <summary>
     /// Initializes a new instance of the MainViewModel class.
     /// </summary>
     public MainViewModel()
     {

         _charges = new ObservableCollection<BonusChargesValue>();
         ShowFaresCommand = new RelayCommand(GetValues, () => { return true; });

           // if I un-comment the below section the observable is working fine.
       //Using lambda is not helping either 

        /* if (IsInDesignMode)
         {
             // Code runs in Blend --> create design time data.
            // BonusChargesValue bnc = new BonusChargesValue();
             _charges = new ObservableCollection<BonusChargesValue>();
             _charges.Add(new BonusChargesValue { AmountToRecharge = 10.0, BonusAmount = 5, NewBalance = 15, NumberofRides = 5 });
             _charges.Add(new BonusChargesValue { AmountToRecharge = 12.0, BonusAmount = 6, NewBalance = 17, NumberofRides = 6 });
             _charges.Add(new BonusChargesValue { AmountToRecharge = 14.0, BonusAmount = 7, NewBalance = 19, NumberofRides = 7 });
             _charges.Add(new BonusChargesValue { AmountToRecharge = 16.0, BonusAmount = 8, NewBalance = 21, NumberofRides = 8 });
             _charges.Add(new BonusChargesValue { AmountToRecharge = 18.0, BonusAmount = 9, NewBalance = 23, NumberofRides = 9 });
             _charges.Add(new BonusChargesValue { AmountToRecharge = 10.0, BonusAmount = 5, NewBalance = 15, NumberofRides = 5 });
             _charges.Add(new BonusChargesValue { AmountToRecharge = 12.0, BonusAmount = 6, NewBalance = 17, NumberofRides = 6 });
             _charges.Add(new BonusChargesValue { AmountToRecharge = 14.0, BonusAmount = 7, NewBalance = 19, NumberofRides = 7 });
             _charges.Add(new BonusChargesValue { AmountToRecharge = 16.0, BonusAmount = 8, NewBalance = 21, NumberofRides = 8 });
             _charges.Add(new BonusChargesValue { AmountToRecharge = 18.0, BonusAmount = 9, NewBalance = 23, NumberofRides = 9 });
         }
         else
         {
             // Code runs "for real"
             _charges = new ObservableCollection<BonusChargesValue>();
           //  ShowFaresCommand = new RelayCommand(GetValues, () => { return true; });

             ShowFaresCommand = new RelayCommand(() =>
             {


                 CalculateMetroFare cmcf = new CalculateMetroFare();
                 if (!string.IsNullOrWhiteSpace(CurrentBalance))
                 {
                     var chr = cmcf.Add2ExistingCard(Convert.ToInt32(CurrentBalance));

                     foreach (BonusChargesValue bncv in chr)
                     {
                         Charges.Add(bncv);
                     }

                 }
             });

             //_charges = new ObservableCollection<BonusChargesValue>();
             //_charges.Add(new BonusChargesValue { AmountToRecharge = 10.0, BonusAmount = 5, NewBalance = 15, NumberofRides = 5 });
             //_charges.Add(new BonusChargesValue { AmountToRecharge = 12.0, BonusAmount = 6, NewBalance = 17, NumberofRides = 6 });
             //_charges.Add(new BonusChargesValue { AmountToRecharge = 14.0, BonusAmount = 7, NewBalance = 19, NumberofRides = 7 });
             //_charges.Add(new BonusChargesValue { AmountToRecharge = 16.0, BonusAmount = 8, NewBalance = 21, NumberofRides = 8 });
             //_charges.Add(new BonusChargesValue { AmountToRecharge = 18.0, BonusAmount = 9, NewBalance = 23, NumberofRides = 9 });
             //_charges.Add(new BonusChargesValue { AmountToRecharge = 10.0, BonusAmount = 5, NewBalance = 15, NumberofRides = 5 });
             //_charges.Add(new BonusChargesValue { AmountToRecharge = 12.0, BonusAmount = 6, NewBalance = 17, NumberofRides = 6 });
             //_charges.Add(new BonusChargesValue { AmountToRecharge = 14.0, BonusAmount = 7, NewBalance = 19, NumberofRides = 7 });
             //_charges.Add(new BonusChargesValue { AmountToRecharge = 16.0, BonusAmount = 8, NewBalance = 21, NumberofRides = 8 });
             //_charges.Add(new BonusChargesValue { AmountToRecharge = 18.0, BonusAmount = 9, NewBalance = 23, NumberofRides = 9 });
         } */


     }
     private void GetValues()
     {

         CalculateMetroFare cmcf = new CalculateMetroFare();
         if (!string.IsNullOrWhiteSpace(CurrentBalance))
         {
             var chr = cmcf.Add2ExistingCard(Convert.ToInt32(CurrentBalance));

             foreach (BonusChargesValue bncv in chr)
             {
                 Charges.Add(bncv);
             }

         }

     }
 }

查看模型

{{1}}

我不确定我做错了什么。任何帮助或指针都表示赞赏。

1 个答案:

答案 0 :(得分:0)

我可以在这里看到几件事:

首先你的ChargesListPropertyName是错误的,它应该是“费用”而不是“ChargeList”。 如果您正在使用MVVM Light,那么有更好的方法来调用PropertyChanged,这会阻止您再次犯这种错误(我稍后会让您检查)。

然后你的公开ObservableCollection费用是_charges的访问者,他们也是公开的。您应该将_charges设置为private(并将其设置为null是无用的)。

最后,您的ItemsSource设置为观看费用。因此,无论您在viewmodel的构造函数之外更新_charges,List都不会知道发生了什么。我的意思是你应该总是更新费用而不是_费用。

进行这些修改并告诉我们它是否有帮助。如果没有,请更新您的代码以向我们展示您修改的内容。