WPF Convert 为 ObservableCollection 调用一次
WPF Convert Called Once for ObservableCollection
我的 wpf 应用程序中有 2 个网格,Grid Parent,Grid Child。当用户 select 父网格中的记录时,子网格显示该父网格记录的条目。在更改父项中的每个记录时,子项重新绑定与其对应的新值。将鼠标悬停在每一行上时,我设置了一个转换器,该转换器可以显示或隐藏在该记录的一列中的图标中。
问题: 当第一次绑定子网格时,鼠标悬停在记录上时它会调用该转换器。一旦我更改了父项中的记录,子网格就会重新绑定,但是当鼠标悬停在这些记录上时,不会调用转换器来显示隐藏图标。它会记住转换器返回的最后一个值。
要求的行为:要求的行为是转换器应在每一行鼠标悬停时调用。
我无法在此处粘贴实际代码,因此我制作了一个示例项目,如果我解决了该示例中的问题,它可能会解决我的问题。
注意:为了简单起见,我粘贴了示例项目的全部代码你只需要在项目[=中创建这些文件 67=].
BaseNotifyChanged.cs
public class BaseNotifyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberName] string propertyname = "")
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyname));
}
}
}
型号:Person.cs
public class Person : BaseNotifyChanged
{
private string _name;
public string Name
{
get { return _name; }
set
{
if (this._name != value)
{
this._name = value;
this.RaisePropertyChanged();
}
}
}
private string _email;
public string Email
{
get { return _email; }
set
{
if (this._email != value)
{
this._email = value;
this.RaisePropertyChanged();
}
}
}
}
查看模型:Employees.cs
public class Employees: BaseNotifyChanged
{
public Employees()
{
this.Employee = new ObservableCollection<Person>()
{
new Person(){ Name = "Zeb", Email = "zeb@gmail.com"},
new Person(){ Name = "Asad", Email = "asad@gmail.com"},
new Person(){ Name = "Javeed", Email = "javeed@gmail.com"}
};
}
private ObservableCollection<Person> _employee;
public ObservableCollection<Person> Employee
{
get { return _employee; }
set
{
if (this._employee != value)
{
this._employee = value;
this.RaisePropertyChanged();
}
}
}
}
查看:MainWindow.xaml
<Grid>
<Grid.Resources>
<localCnr:ListToStringConverter x:Key="LtSCtr"></localCnr:ListToStringConverter>
</Grid.Resources>
<StackPanel>
<TextBlock Text="{Binding Employee, Converter={StaticResource LtSCtr}}"/>
<Button Content="Add New Employee" Click="ButtonBase_OnClick"/>
</StackPanel>
</Grid>
查看代码背后:MainWindow.xaml.cs
public partial class MainWindow : Window
{
public Employees employee { get; set; }
public MainWindow()
{
InitializeComponent();
employee = new Employees();
this.DataContext = employee;
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
employee.Employee.Add(new Person(){ Name = "New Employee", Email = "new@gmail.com"});
}
}
转换器:ListToStringConverter.cs
public class ListToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ObservableCollection<Person> employess = value as ObservableCollection<Person>;
StringBuilder sb = new StringBuilder();
foreach (Person person in employess)
{
sb.Append(person.Name + " , ");
}
return sb.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
据我所知,在我的原始场景中,网格正在重新绑定,但作为集合对象,它本身并没有更新,而是添加或删除了一个值,因此它没有调用转换。有什么建议吗?
提前致谢
向集合中添加元素时,您并未修改 Employee
属性,因此不会引发 NotifyPropertyChanged 事件。
一个简单的解决方法是在 ButtonBase_OnClick
.
的末尾调用 employee.RaisePropertyChanged("Employee")
只是为了解释上面的答案,因为employee.Employee是一个ObservableCollection,你会期望它自动通知有界的TextBlock,但是当Employee列表更新时TextBlock仍然保持不变。
解释是文本 属性 不需要集合,因此不会侦听 CollectionChanged 事件。换句话说,ObservableCollection<Person>
正在通知更改,但没有人在收听通知。使用 KooKiz 方法明确告诉 TextBlock,就好像 "Emplyoee" 属性 已更改(而不仅仅是它后面的集合),TextBlock 正在侦听。
我的 wpf 应用程序中有 2 个网格,Grid Parent,Grid Child。当用户 select 父网格中的记录时,子网格显示该父网格记录的条目。在更改父项中的每个记录时,子项重新绑定与其对应的新值。将鼠标悬停在每一行上时,我设置了一个转换器,该转换器可以显示或隐藏在该记录的一列中的图标中。
问题: 当第一次绑定子网格时,鼠标悬停在记录上时它会调用该转换器。一旦我更改了父项中的记录,子网格就会重新绑定,但是当鼠标悬停在这些记录上时,不会调用转换器来显示隐藏图标。它会记住转换器返回的最后一个值。
要求的行为:要求的行为是转换器应在每一行鼠标悬停时调用。
我无法在此处粘贴实际代码,因此我制作了一个示例项目,如果我解决了该示例中的问题,它可能会解决我的问题。
注意:为了简单起见,我粘贴了示例项目的全部代码你只需要在项目[=中创建这些文件 67=].
BaseNotifyChanged.cs
public class BaseNotifyChanged : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberName] string propertyname = "")
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyname));
}
}
}
型号:Person.cs
public class Person : BaseNotifyChanged
{
private string _name;
public string Name
{
get { return _name; }
set
{
if (this._name != value)
{
this._name = value;
this.RaisePropertyChanged();
}
}
}
private string _email;
public string Email
{
get { return _email; }
set
{
if (this._email != value)
{
this._email = value;
this.RaisePropertyChanged();
}
}
}
}
查看模型:Employees.cs
public class Employees: BaseNotifyChanged
{
public Employees()
{
this.Employee = new ObservableCollection<Person>()
{
new Person(){ Name = "Zeb", Email = "zeb@gmail.com"},
new Person(){ Name = "Asad", Email = "asad@gmail.com"},
new Person(){ Name = "Javeed", Email = "javeed@gmail.com"}
};
}
private ObservableCollection<Person> _employee;
public ObservableCollection<Person> Employee
{
get { return _employee; }
set
{
if (this._employee != value)
{
this._employee = value;
this.RaisePropertyChanged();
}
}
}
}
查看:MainWindow.xaml
<Grid>
<Grid.Resources>
<localCnr:ListToStringConverter x:Key="LtSCtr"></localCnr:ListToStringConverter>
</Grid.Resources>
<StackPanel>
<TextBlock Text="{Binding Employee, Converter={StaticResource LtSCtr}}"/>
<Button Content="Add New Employee" Click="ButtonBase_OnClick"/>
</StackPanel>
</Grid>
查看代码背后:MainWindow.xaml.cs
public partial class MainWindow : Window
{
public Employees employee { get; set; }
public MainWindow()
{
InitializeComponent();
employee = new Employees();
this.DataContext = employee;
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
employee.Employee.Add(new Person(){ Name = "New Employee", Email = "new@gmail.com"});
}
}
转换器:ListToStringConverter.cs
public class ListToStringConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
ObservableCollection<Person> employess = value as ObservableCollection<Person>;
StringBuilder sb = new StringBuilder();
foreach (Person person in employess)
{
sb.Append(person.Name + " , ");
}
return sb.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
据我所知,在我的原始场景中,网格正在重新绑定,但作为集合对象,它本身并没有更新,而是添加或删除了一个值,因此它没有调用转换。有什么建议吗? 提前致谢
向集合中添加元素时,您并未修改 Employee
属性,因此不会引发 NotifyPropertyChanged 事件。
一个简单的解决方法是在 ButtonBase_OnClick
.
employee.RaisePropertyChanged("Employee")
只是为了解释上面的答案,因为employee.Employee是一个ObservableCollection,你会期望它自动通知有界的TextBlock,但是当Employee列表更新时TextBlock仍然保持不变。
解释是文本 属性 不需要集合,因此不会侦听 CollectionChanged 事件。换句话说,ObservableCollection<Person>
正在通知更改,但没有人在收听通知。使用 KooKiz 方法明确告诉 TextBlock,就好像 "Emplyoee" 属性 已更改(而不仅仅是它后面的集合),TextBlock 正在侦听。