在StackPanel中绑定到属性不起作用
本文关键字:属性 不起作用 绑定 StackPanel | 更新日期: 2023-09-27 17:52:12
我正在构建一个Windows 8小应用程序,经过几个小时的绞尽脑汁,我不明白为什么我的绑定不能工作。我有这个ViewModel:
public class DetailsViewModel : ViewModelBase
{
private BookDataService _bookDataService;
private ObservableCollection<Book> _authorsBooks;
public ObservableCollection<Book> AuthorsBooks
{
get
{
return _authorsBooks;
}
set
{
_authorsBooks = value;
OnPropertyChanged("AuthorsBooks");
}
}
private string _bookTitle;
public string BookTitle
{
get
{
return _bookTitle;
}
set
{
_bookTitle = value;
OnPropertyChanged("BookTitle");
}
}
public DetailsViewModel()
{
_authorsBooks = new ObservableCollection<Book>();
}
public async Task GetBookDetails(string bookID)
{
_bookDataService = new BookDataService();
var remoteResults = await _bookDataService.GetBookDetailsAsync(bookID);
_bookTitle = remoteResults.Title;
}
public async Task GetAuthorBooks(string authorID)
{
_bookDataService = new BookDataService();
var remoteResults = await _bookDataService.GetAuthorBooksAsync(authorID);
foreach (var book in remoteResults)
_authorsBooks.Add(book);
}
}
这是StackPanel的XAML:
<StackPanel x:Name="BookDetailsStackPanel"
Grid.Row="0"
Orientation="Horizontal"
DataContext="{Binding DetailsViewModel}">
<Image Source="{Binding LargeImage}"
Width="200" Height="300"
VerticalAlignment="Top"
HorizontalAlignment="Left"
Margin="24"/>
<StackPanel Orientation="Vertical">
<TextBlock Margin="24" Text="{Binding BookTitle}" Foreground="Black"/>
<TextBlock Margin="24" Text="{Binding Author.Name}" Foreground="Black"/>
<TextBlock Margin="24" Foreground="Black">
<Run Text="{Binding Rating}"/>
<Run Text="("/>
<Run Text="{Binding RatingsCount}"/>
<Run Text=")"/>
</TextBlock>
</StackPanel>
</StackPanel>
我在代码后面初始化ViewModel并获得数据:
private DetailsViewModel _detailsViewModel = new DetailsViewModel();
public DetailsViewModel DetailsViewModel
{
get { return this._detailsViewModel; }
}
async void DetailsPage_Loaded(object sender, RoutedEventArgs e)
{
BookDetailsProgressRing.IsActive = true;
await _detailsViewModel.GetBookDetails(_bookID);
BookDetailsProgressRing.IsActive = false;
}
显然,我只是在谈论BookTitle
属性,一旦我知道我的代码出了什么问题,我就会设置其他属性。
经过几个小时的调试,我可以肯定地说,BookTitle
被设置为正确的值,但它只是不绑定到TextBlock
。此外,我在同一页上有一个ListView
,它绑定到AuthorsBooks
属性,它工作得很好,所以我认为我的问题是StackPanel
。
同时,当运行应用程序时,没有任何绑定错误显示在输出窗口。
有什么建议吗?
我刚刚遇到了一个类似的问题-在更新ObservableCollection后无法获得属性更改。参考在Windows Phone开发中心的Windows Phone应用程序中实现模型-视图-视图模式的教程,我将PropertyChangedEventHandler和RaisePropertyChanged事件添加到类中,它工作了!见下文:
public class ActivityLog : INotifyPropertyChanged
{
public string strLogID { get; set; } //unique id for the log entry.
private string _strLogDate;
public string strLogDate
{
get
{
return _strLogDate;
}
set
{
_strLogDate = value;
RaisePropertyChanged("strLogDate");
}
}
public bool booIsUploaded { get; set; }
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string propertyName)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
就像Mathew在评论中说的,你直接更新字段_bookTitle
,而不是通过它的属性设置器,所以PropertyChanged
事件,假设"告诉"你的文本块更新永远不会引发。
这在所有与作者相关的事情中起作用的原因是因为使用了ObservableCollection
。绑定的工作方式是必须引发一个事件,列出相关的属性名称,通知相关的UIElement
进行更新。在大多数情况下,当我们为属性设置一个新值时,这个值就会累积,这就是为什么在那里放置OnPropertyChanged
调用非常常见的原因。但是对于列表,情况就有点不同了,因为我们不仅要知道什么时候给整个列表设置了一个新值,还要知道列表中的项什么时候被添加或删除了。ObservableCollection
就是这样做的,每次添加或删除一个项目时,它都会引发一个事件(如果你不愿意,你甚至可以注册到这个事件)。
回到您的代码,现在您知道了,看看Get方法之间的关键区别。GetBookDetails
直接更新_bookTitle
,因此没有事件被引发,你的TextBlock
没有理由知道它需要更新它的值。在GetAuthorBooks
中,你也直接处理_authorsBooks
,但你不改变它的值,只是简单地添加项目,现在就像上一个例子一样,你的OnPropertyChanged
方法永远不会被调用,但是ObservableCollection
在添加项目时引发它自己的事件,因此告诉相关的UIElement
更新。
事实上,如果你只打算从你的ObservableCollection
中添加或删除项目,而不改变它的值,你甚至不需要在setter中调用OnPropertyChanged
,只有当你用一个不同的列表替换当前列表时,你才需要调用它