WPF 数据绑定只能生效一次

darthpanda 2017-09-02 06:06:54
刚开始学 wpf。
这里想做的事情是把前面通过 API 获得的某个菜的原料(以 List<string>存储),点击加入购物车按钮后显示在购物车(一个 ListBox) 里。
思路很简单就是把购物车 ListBox 绑定到一个 ShopList 类实例的 属性上,然后在按钮点击的 event handler 中改变 ShopList 属性值,然后就会自动更新显示。
然而实际写出来发现,第一次点击之后,购物车中的确正常显示了几个原料的名字,但再加入另一个菜时,虽然还是正常更新了 ShopList 实例的属性,但却没有更新绑定的 ListBox 了。

如图:
第一次点击按钮,正常显示在了右边


第二次点击按钮,右边无反应。但通过 debugger 查看,ShopListBox 的 ItemsToBuy 属性还是正常更新了的。所以我猜测是数据绑定上出的问题。



// xaml

<ListBox Name="ItemsToBuy" ItemsSource="{Binding ItemsFromRecipe}" /> // 显示某个菜单中的原料,这部分显示正常
<Button Name="AddButton" Content="Add To List" Grid.Row="3" Click="AddButton_Click"/> // 想在点击这个按钮时把原料加入下面的 ListBox。

<ListBox Name="ShopListBox" ItemsSource="{Binding ItemsToBuy}" Grid.Column="1" ScrollViewer.VerticalScrollBarVisibility="Auto">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Name="ItemName" Text="{Binding}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>


AddButton 的点击事件是这么写的:

public partial class MainWindow : Window
{
ShopList shopList = new ShopList();
public MainWindow()
{
InitializeComponent();
ShopListBox.DataContext = shopList;
}

private void AddButton_Click(object sender, RoutedEventArgs e)
{
shopList.AddToList(recipeItems.ItemsFromRecipe); // recipeItems.ItemsFromRecipe 的代码就不贴了,可以确保这部分没问题,在 debugger 里看,是正常返回了一个 List<string> 的
}
}
}


最后是 ShopList 类:

public class ShopList : INotifyPropertyChanged
{
private List<string> itemsToBuy;
public List<string> ItemsToBuy // ShopListBox 绑的就是这个属性
{
get { return itemsToBuy; }
}
public event PropertyChangedEventHandler PropertyChanged;

public void AddToList(List<string>items)
{
var tempList = itemsToBuy==null?new List<string>():itemsToBuy;

foreach (var item in items)
{
if (!tempList.Contains(item))
{
tempList.Add(item);
};
}
itemsToBuy = tempList;
OnPropertyChanged(nameof(itemsToBuy));
}

private void OnPropertyChanged([CallerMemberName]string callProperty = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(callProperty));
}
}
}


...全文
1553 6 打赏 收藏 转发到动态 举报
写回复
用AI写文章
6 条回复
切换为时间正序
请发表友善的回复…
发表回复
飞车之 2018-01-29
  • 打赏
  • 举报
回复
之前也遇到过同样的问题,之后也是跟楼上说的改成ObservableCollection就可以了
  • 打赏
  • 举报
回复
引用 4 楼 darthpanda的回复:
[quote=引用 2 楼 duanzi_peng 的回复:] ItemsToBuy换成ObservableCollection动态数据集合,并增加set方法。set方法很重要。任何一个VM中的属性更新,都必须有set方法,然后调用OnPropertyChanged方法进行UI更新通知。
感谢回复 换成了 ObservableCollection 后问题就解决了 但我觉得这里不应该有 set 方法吧,我是专门把允许外部代码修改 ItemsToBuy 的操作 AddToList 封装在了一个 public method 里边,这样就不允许外部直接对 ItemsToBuy 进行修改了。 mvvm 这个模式确实不了解,要多多学习:)[/quote] 那就多学习了。
darthpanda 2017-09-03
  • 打赏
  • 举报
回复
引用 2 楼 duanzi_peng 的回复:
ItemsToBuy换成ObservableCollection动态数据集合,并增加set方法。set方法很重要。任何一个VM中的属性更新,都必须有set方法,然后调用OnPropertyChanged方法进行UI更新通知。
感谢回复 换成了 ObservableCollection 后问题就解决了 但我觉得这里不应该有 set 方法吧,我是专门把允许外部代码修改 ItemsToBuy 的操作 AddToList 封装在了一个 public method 里边,这样就不允许外部直接对 ItemsToBuy 进行修改了。 mvvm 这个模式确实不了解,要多多学习:)
  • 打赏
  • 举报
回复
刚学就要理解MVVM模式,很显然你把vm指定给了一个控件,而不是整个窗口对象this。如果vm中有其他属性要显示?你要怎么做??其实网上随便找篇Wpf MVVM的文章就跟容易理解DataContext应该指定给谁。
  • 打赏
  • 举报
回复
ItemsToBuy换成ObservableCollection动态数据集合,并增加set方法。set方法很重要。任何一个VM中的属性更新,都必须有set方法,然后调用OnPropertyChanged方法进行UI更新通知。
darthpanda 2017-09-02
  • 打赏
  • 举报
回复
补充,在 debugger 里加了断点看, 第二次点击时候, shopList 的 OnPropertyChange 方法也是运行了的……所以实在不明白为啥绑定的 ListBox 就不更新呢……

8,757

社区成员

发帖
与我相关
我的任务
社区描述
WPF/Silverlight相关讨论
社区管理员
  • WPF/Silverlight社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧