WPF ListBox 属性绑定未更新
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22547062/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF ListBox property binding not updating
提问by qJake
I have the following setup:
我有以下设置:
XAML:
XAML:
<ListBox x:Name="MyList" ItemsSource="{Binding MyItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Image Height="20" Width="20" Visibility="{Binding HasInformation, Converter={StaticResource VC}, ConverterParameter=True}" Source="/path/to/information.png" />
<TextBlock Text="{Binding Name}" VerticalAlignment="Center" Padding="5,0" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
Note: The ConverterParameter being passed in simply controls whether the visibility is "Collapsed" (False), or "Hidden" (True), so in this case, I want the visibility to be Hidden.
注意:传入的 ConverterParameter 只是控制可见性是“折叠”( False) 还是“隐藏”( True),因此在这种情况下,我希望可见性为Hidden。
ViewModel Snippet:
视图模型片段:
private ObservableCollection<IItem> _MyItems;
public ObservableCollection<IItem> MyItems
{
get
{
return _MyItems;
}
set
{
NotifyPropertyChanged(ref _MyItems, value, "MyItems");
}
}
private IItem _SelectedItem;
public IItem SelectedItem
{
get
{
return _SelectedItem;
}
set
{
NotifyPropertyChanged(ref _SelectedItem, value, "SelectedItem");
}
}
IItem:
项目:
public interface IItem
{
string Name { get; }
bool HasInformation { get; set; }
}
I populate an implementation of a list of IItemfrom a database into the list, and the information icon appears appropriately if HasInformationis true. This all works correctly.
我将IItem来自数据库的列表的实现填充到列表中,如果HasInformation为真,则信息图标会适当地出现。这一切正常。
However, if I set HasInformationby hand, the view does not update. I have tried:
但是,如果我HasInformation手动设置,视图不会更新。我试过了:
In the ViewModel:
在视图模型中:
OnPropertyChanged("MyItems");
MyItems[MyItems.IndexOf(SelectedItem)].HasInformation = true;
// Note that "SelectedItem" is persisted correctly, and always
// points to the selected item that we want to update.
In the code behind:
在后面的代码中:
MyList.GetBindingExpression(ItemsControl.ItemsSourceProperty).UpdateTarget();
All of these fire the getter of the MyItemsproperty, but the view never updates and the icon never displays.I have ensured that the HasInformationproperty of the item that I updated does, in fact, remain true. I've attached to the PropertyChangedevent to ensure that it's firing a property change for "MyItems"(it is, this also fires the getter), and I've even ensured that it's calling the value converter with the correct value for the HasInformationproperty (it is!), so what am I missing? Is there something weird with image showing/hiding or visibility value conversion that I'm not handling correctly?
所有这些都会触发MyItems属性的 getter ,但视图永远不会更新并且图标永远不会显示。我已确保HasInformation我更新的项目的属性实际上保持不变true。我已经附加到PropertyChanged事件以确保它触发属性更改"MyItems"(它也是,这也会触发 getter),我什至确保它使用正确的HasInformation属性值调用值转换器(它是! ),那我错过了什么?我没有正确处理图像显示/隐藏或可见性值转换是否有什么奇怪的地方?
回答by Stephen Zeng
ObservableCollection only notifies the collection changes not the changes in each of the item. In order to achieve your goal one of options is to change the IItem from interface to a class which implements INotifyPropertyChanged interface (or implement it in the IItem concrete type), and hook it with the ViewModel's PropertyChanged delegate (remember to unsubscribe it). See some of my code below.
ObservableCollection 只通知集合的变化,而不是每个项目的变化。为了实现您的目标,一种选择是将 IItem 从接口更改为实现 INotifyPropertyChanged 接口的类(或在 IItem 具体类型中实现它),并将其与 ViewModel 的 PropertyChanged 委托挂钩(记得取消订阅)。请参阅下面的一些我的代码。
ViewModel
视图模型
public class MyViewModel: INotifyPropertyChanged
{
private ObservableCollection<Item> _MyItems;
public ObservableCollection<Item> MyItems
{
get
{
return _MyItems;
}
set
{
if (_MyItems != null)
{
foreach (var item in _MyItems)
{
item.PropertyChanged -= PropertyChanged;
}
}
if (value != null)
{
foreach (var item in value)
{
item.PropertyChanged += PropertyChanged;
}
}
OnPropertyChanged();
}
}
private Item _SelectedItem;
public Item SelectedItem
{
get
{
return _SelectedItem;
}
set
{
_SelectedItem = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}
Item
物品
public class Item : INotifyPropertyChanged
{
private string _name;
private bool _hasInformation;
public string Name
{
get { return _name; }
set
{
_name = value;
OnPropertyChanged();
}
}
public bool HasInformation
{
get { return _hasInformation; }
set
{
_hasInformation = value;
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
}
}

