在以下绑定中,
<TextBlock Text="{Binding Path=., StringFormat=TotalPages:{0}, Converter={StaticResource totalPagesConverter}}"/>
totalPagesConverter
取ObservableCollection<MyFileInfo>
并返回总页数。
这仅适用于第一次,但在MyFileInfo
对象的属性更改时不会更新。请注意,我确实为INotifyPropertyChanged
实施了MyFileInfo
,并且当它们绑定到属性MyFileInfo
时,事情会正确更新。但是当绑定到Collection
个这样的对象时,显然缺少某些东西。如何绑定到Collection以使其正确更新?谢谢!
更新谢谢大家! MyFileInfo
和转换器的属性如下所示:
MyFileInfo
课程
public class MyFileInfo : INotifyPropertyChanged
{
private Boolean ifPrint;
private Boolean isValid;
public string Filename {
get; set;
}
public string Filepath {
get; set;
}
public int Copies {
get; set;
}
public int Pages {
get; set;
}
public Boolean IfPrint {
get{
return this.ifPrint;
}
set{
if (this.ifPrint != value){
this.ifPrint = value;
onPropertyChanged("IfPrint");
}
}
}
public Boolean IsValid {
get {
return this.isValid;
}
set {
if (this.isValid!= value) {
this.isValid = value;
onPropertyChanged("IsValid");
}
}
}
private void onPropertyChanged(string propertyName) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
转换器类
public class TotalPagesConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
ObservableCollection<MyFileInfo> lst = (ObservableCollection<MyFileInfo>)value;
int t = 0;
foreach(MyFileInfo f in lst){
t += (f.IsValid && f.IfPrint) ? f.Pages : 0;
}
return t.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) {
throw new NotImplementedException();
}
}
转换器上的一点:我有一个CheckBox
供用户选择要打印的文件。每次切换CheckBox
时,都会翻转IfPrint
对象的MyFileInfo
布尔属性。此转换器遍历所有IfPrint && IsValid
个文件以重新计算总页数,并在GUI上更新新的待打印页面(理想情况下)。这不是那么有效,但是列表很短(&lt; 10)。欢迎任何其他想法!
答案 0 :(得分:2)
这仅适用于第一次,但在更改MyFileInfo对象的属性时不会更新。
ObservableCollection
只会在集合本身发生变化时引发通知事件,例如添加或删除项目。
如果你想让这个系列同时发射一个&#34;我已经改变了#34;消息,当集合中的任何项目发生变化时,您必须自己连接属性更改的处理程序。
public MyViewModel()
{
FileInfoCollection = new ObservableCollection<MyFileInfo>();
// Hook up initial changed handler. Could also be done in setter
FileInfoCollection.CollectionChanged += FileInfoCollection_CollectionChanged;
}
void FileInfoCollection_CollectionChanged(object sender, CollectionChangedEventArgs e)
{
if (e.NewItems != null)
{
foreach(MyFileInfo item in e.NewItems)
{
item.PropertyChanged += MyFileInfo_PropertyChanged;
}
}
if (e.OldItems != null)
{
foreach(MyFileInfo item in e.OldItems)
{
item.PropertyChanged -= MyFileInfo_PropertyChanged;
}
}
}
void MyFileInfo_PropertyChanged(object sender, PropertyChange e)
{
// Whenever a FileInfo changes, raise change notification for collection
RaisePropertyChanged("FileInfoCollection");
}
那就是说,我不明白为什么每当集合中项目的属性发生变化时,需要重新评估集合中项目计数的绑定,除非你做某种事情在转换器内进行过滤。
另外,如果您只是绑定到集合的计数,那么您是否只能绑定到.Count
上的ObservableCollection<T>
属性?
<TextBlock Text="{Binding Path=Count, StringFormat=TotalPages:{0}}" />
答案 1 :(得分:1)
如果我理解正确,您可以在某种列表/网格中列出项目,每个项目都有一个绑定到IfPrint属性的复选框。当用户单击该复选框时,您希望文本块更新并显示将IfPrint和IsValid设置为true的MyFileInfos的数量,对吗?
绑定仅侦听对象上的PropertyChanged事件,该对象是其DataContext。这意味着对IfPrint进行更改的唯一控件是复选框。任何其他控件做出反应的唯一方法是手动传达更改 - 最简单的方法是创建事件:
public class MyFileInfo : INotifyPropertyChanged
{
private Boolean ifPrint;
private Boolean isValid;
...
public Boolean IfPrint {
get{
return this.ifPrint;
}
set{
if (this.ifPrint != value){
this.ifPrint = value;
onPropertyChanged("IfPrint");
OnCanPrintChanged();
}
}
}
public Boolean IsValid {
get {
return this.isValid;
}
set {
if (this.isValid!= value) {
this.isValid = value;
onPropertyChanged("IsValid");
OnCanPrintChanged();
}
}
}
private void onPropertyChanged(string propertyName) {
if (PropertyChanged != null) {
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
private void OnCanPrintChanged()
{
if (CanPrintChanged != null)
{
CanPrintChanged(this, EventArgs.Empty);
}
}
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler CanPrintChanged;
}
在您的代码隐藏类中,您为列表中的每个MyFileInfo连接此事件,并更新codebehind / viewmodel中的属性:
public class MyCodeBehind : INotifyPropertyChanged
{
private int _printablePageCount = 0;
public int PrintablePageCount
{
get { return _printablePageCount; }
set
{
return _printablePageCount = value;
OnPropertyChanged("PrintablePageCount");
}
}
private void OnCanPrintChanged(object sender, EventArgs arg)
{
int t = 0;
foreach(MyFileInfo f in lst)
{
if (f.IsValid && f.IfPrint)
{
t++;
}
}
PrintablePageCount = t;
}
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
在您的XAML中,您可以绑定到PrintablePageCount(无需转换器):
<TextBlock Text="{Binding Path=PrintablePageCount, StringFormat=TotalPages:{0}}"/>
答案 2 :(得分:0)
在设置ObservableCollection属性的值时,不要忘记引发OnPropertyChanged事件。
public ObservableCollection<MyFileInfo> FileInfos
{
get{return fileInfos;}
set
{
if(fileInfos != value)
{
fileInfos = value;
OnPropertyChanged("FileInfos");
}
}}
Add Mode = TwoWay to binding。
<TextBlock Text="{Binding Path=FileInfos, Mode=TwoWay, StringFormat=TotalPages:{0}, Converter={StaticResource totalPagesConverter}}"/>