我正在设置一个ListView,其Source
属性设置为我的一类ivar,名为Cat
。
每个Cat
都有ObservableCollection
个Trait
个对象:
private ObservableCollection<Trait> _traits = new ObservableCollection<Trait>();
public ObservableCollection<Trait> Traits
{
get
{
return _traits;
}
}
public void AddTrait(Trait t)
{
_traits.Add(t);
// Is this redundant? Is one better than the other?
this.OnPropertyChanged("_traits");
this.OnPropertyChanged("Traits");
}
public IEnumerator<Object> GetEnumerator()
{
return _traits.GetEnumerator();
}
然后我将Source
属性分配给此Traits
集合:
this.CollectionViewSource.Source = CurrentCat.Traits;
此操作正常,Trait
对象在我的ListView
中正确显示。
问题是对此基础_traits
集合的更改不会导致UI正确更新。例如,这个:
void AddTraitButton_Click(object sender, RoutedEventArgs e)
{
if (this.CurrentCat != null)
{
this.CurrentCat.AddTrait(new Trait());
}
}
在UI中似乎没有任何影响 ,但如果我像这样重置Source
属性:
var oldSource = this.CollectionViewSource.Source;
this.CollectionViewSource.Source = null;
this.CollectionViewSource.Source = oldSource;
然后ListView
正确更新。但是,我确信必须有一些我缺少的东西,因为我希望UI能够在添加/删除项目时更新。
修改:CollectionViewSource
正在应用于我的XAML文件中的ListView
:
<CollectionViewSource x:Name="CollectionViewSource" x:Key="CollectionViewSource" />
...
<ListView x:Name="ItemListView" ItemsSource="{Binding Source={StaticResource CollectionViewSource}}" ...
答案 0 :(得分:0)
我现在似乎无法找到它,但我似乎记得绑定到CollectionViewSource
的一些问题。您是否尝试直接绑定到CurrentCat.Traits
并在代码隐藏中设置this.DataContext = this
(我假设您不在此处使用MVVM)?
<ListView x:Name="ItemListView" ItemsSource="{Binding CurrentCat.Traits}" />
答案 1 :(得分:0)
我没有直接绑定到CollectionViewSource并替换它的Source
来强制刷新,我相信你想要绑定到CVS的View
属性......
<ListView x:Name="ItemListView"
ItemsSource="{Binding Source={StaticResource CollectionViewSource}, Path=View}" ...
...并在更新源集合后调用CollectionViewSource.Refresh()
。
void AddTraitButton_Click(object sender, RoutedEventArgs e)
{
if (this.CurrentCat != null)
{
this.CurrentCat.AddTrait(new Trait());
this.CollectionViewSource.Refresh();
}
}
另外,还有一些注意事项,因为您似乎对.NET / WPF约定相对较新:
this
关键字对类成员进行前缀通常是多余的,除非在作用域中有另一个具有相同名称的标识符如果你在WPF中做任何非平凡的事情,那么值得探索MVVM及相关模式;它们可以帮助您保持视图(XAML对象)尽可能轻松且易于更改。
在您的情况下,例如,我假设您显示的代码来自任何Window或UserControl包含ListView的代码隐藏。遵循MVVM模式将涉及创建一个单独的“ViewModel”类,该类将包含Traits
集合并通过CollectionViewSource
公开它(使用View属性,正如我所提到的)。然后,您的UserControl将ViewModel的实例指定为其DataContext
,并且ListView可以绑定到公开的CollectionView。
答案 2 :(得分:0)
您可以专门使用ObservableCollection。虽然存在一个问题 - 但它不会在IsInDesignMode中显示数据。也许将来它会有所改善。
public class MainViewModel : ViewModelBase
{
...
private ObservableCollection<PartViewModel> _parts;
public ObservableCollection<PartViewModel> Parts
{
get
{
if (_parts == null)
{
_parts = new ObservableCollection<PartViewModel>();
_parts.CollectionChanged += _parts_CollectionChanged;
}
return _parts;
}
}
object m_ReorderItem;
int m_ReorderIndexFrom;
void _parts_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Remove:
m_ReorderItem = e.OldItems[0];
m_ReorderIndexFrom = e.OldStartingIndex;
break;
case NotifyCollectionChangedAction.Add:
if (m_ReorderItem == null)
return;
var _ReorderIndexTo = e.NewStartingIndex;
m_ReorderItem = null;
break;
}
}
private PartViewModel _selectedItem;
public PartViewModel SelectedItem
{
get
{
return _selectedItem;
}
set
{
if (_selectedItem != value)
{
_selectedItem = value;
RaisePropertyChanged("SelectedItem");
}
}
}
...
#region ViewModelBase
public override void Cleanup()
{
if (_parts != null)
{
_parts.CollectionChanged -= _parts_CollectionChanged;
}
base.Cleanup();
}
#endregion
}
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
<Grid.Resources>
<CollectionViewSource x:Name="PartsCollection" Source="{Binding Parts}"/>
</Grid.Resources>
<ListView Margin="20" CanReorderItems="True" CanDragItems="True" AllowDrop="True"
ItemsSource="{Binding Source={StaticResource PartsCollection}}" SelectedItem="{Binding SelectedItem, Mode=TwoWay}" SelectionMode="Single">
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"></Setter>
</Style>
</ListView.ItemContainerStyle>
<ListView.ItemTemplate>
...
</ListView.ItemTemplate>
</ListView>
</Grid>
答案 3 :(得分:-5)
查看我提出的关于获取ListView绑定并为所有CRUD操作工作的演示。
http://www.flaskofespresso.com/2012/01/windows-8-metro-app-listview-binding-and-editing/