我最近在我的一个域实体中添加了一个Disabled属性。我在视图模型中有List<T>
个实体。我刚刚更改了getter以根据UI设置过滤列表,以选择性地显示已禁用的项目。
public ObservableCollection<CustomVariableGroup> CustomVariableGroups
{
get
{
if (this.ShowDisabled) { return this._customVariableGroups; }
return new ObservableCollection<CustomVariableGroup>(this._customVariableGroups.Where(x => x.Disabled == false));
}
}
问题在于,当我现在尝试这样做时(在相同的视图模型中),该项目不会被添加到集合中。
this.CustomVariableGroups.Add(newGroup);
我想我知道原因:newGroup被添加到新的ObservableCollection<T>
,而不是_customVariableGroups的支持字段。
如果LINQ Where()扩展方法能够返回ObservableCollection<T>
(私有支持字段本身的类型)而不是IEnumerable,我认为我没有这个问题。现在,由于Where()返回IEnumerable<T>
,我需要将其包含在新的ObservableCollection<T>
中。
在同一视图模型中添加新项目的正确/最佳方式是什么?我是否需要将其直接添加到私人支持字段?我不想这样做,因为我不想记住不要使用该属性本身。
答案 0 :(得分:1)
而不是直接绑定到您的集合,您可以绑定到 ICollectionView 并在Disabled属性中设置Filter。无需更改源集合。
编辑:
视图模型:
//this collection just init once - eg. in ctor, use add, remove, clear to alter
public ObservableCollection<CustomVariableGroup> CustomVariableGroups {get; private set; }
//create just once in ctor
public ICollectionView MyView {get; private set;}
//ctor
this.CustomVariableGroups = new ObservableCollection<CustomVariableGroup>();
this.MyView = CollectionViewSource.GetDefaultView(this.CustomVariableGroups);
//in your disabled property set the filter
public bool ShowDisabled
{
get { return _showDisabled; }
set {
_showDisabled = value;
if (_showDisabled)
//show just disabled
this.MyView.Filter = (item) =>
{
var myitem = (CustomVariableGroup) item;
return myitem.Disabled;
};
else
{
//show all
this.MyView.Filter = (item) => { return true; };
}
this.NotifyPropertyChanged("ShowDisabled"); }
}
XAML
<CheckBox Content="ShowDisabled" IsChecked="{Binding ShowDisabled}"/>
<ListBox ItemsSource="{Binding MyView}" Grid.Row="1">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
这适用于我的testproject
答案 1 :(得分:1)
正如评论中所提到的,解决这个问题的正确方法是在视图中,而不是视图模型。这只是一个观点问题。我以为我会发布我是如何处理它的,以防万一这会帮助别人。
首先,getter(视图模型)应该每次都返回完整列表:
public ObservableCollection<CustomVariableGroup> CustomVariableGroups
{ get { return this._customVariableGroups; } }
然后,在视图中,我将过滤器事件添加到我的CollectionViewSource:
<CollectionViewSource x:Key="SortedGroups" Source="{Binding CustomVariableGroups}" Filter="CollectionViewSource_Filter">
每次点击Show Disabled复选框时都要刷新列表:
Command="{Binding RefreshVariableGroupCommand}"
然后,在后面的代码中,我实现了过滤器:
private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
CustomVariableGroup customVariableGroup = e.Item as CustomVariableGroup;
if (customVariableGroup == null) { return; }
if ((bool)chkShowDisabled.IsChecked)
{
// Show everything
e.Accepted = true;
return;
}
// We are not showing disabled items, so set disabled items e.Accepted to false.
if (customVariableGroup.Disabled == true)
{
e.Accepted = false;
return;
}
e.Accepted = true;
}
关于这一点,我不喜欢的唯一部分是我正在使用MVVM并试图避免代码隐藏类。但是,拥有它比破解视图模型更好。
答案 2 :(得分:0)
我会维护你的支持列表,然后提高你的ObservableCollection的属性。
public ObservableCollection<CustomVariableGroup> CustomVariableGroups
{
get
{
if (this.ShowDisabled) { return this._customVariableGroups; }
return new ObservableCollection<CustomVariableGroup> (this._customVariableGroups.Where(x => x.Disabled == false));
}
}
// adds to the backing list but raises on property to rebuild and
// return the ObservableCollection
public void AddCustomVariableGroup(CustomVariableGroup newGroup)
{
this._customVariableGroups.Add(newGroup);
OnPropertyChanged("CustomVariableGroups");
}
//Example invocation
AddCustomVariableGroup(newGroup);
答案 3 :(得分:0)
在显示过滤结果时,我遇到了与WinPhone应用程序类似的问题。我的解决方案是绑定到“ShowDisabled”属性更改,并在此事件上简单地Clear()
并在这种情况下将内容读入主Observable:CustomVariableGroups。像这样:
public bool ShowDisabled
{
get
{
return showDisabled;
}
set
{
if (showDisabled!= value)
{
showDisabled = value;
NotifyPropertyChanged("ShowDisabled");
}
}
}
在构造函数中添加:this.PropertyChanged += new PropertyChangedEventHandler(MyViewModel_PropertyChanged);
在事件处理程序中:
void MyViewModel_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "ShowDisabled")
{
CustomVariableGroups.Clear();
foreach (var cvg in AllVariableGroups.Where(x => !x.Disabled))
{
CustomVariableGroups.Add(cvg);
}
}
}
绑定到CustomVariableGroups
的组件应相应更新。
免责声明:当然会对此产生性能影响,您需要决定它是否可以忽略不计。
答案 4 :(得分:0)
我会做类似@Tallmaris的事情,但在MyViewModel_PropertyChanged
中代替这一点:
CustomVariableGroups.Clear();
foreach (var cvg in CustomVariableGroups.Where(x => !x.Disabled))
{
CustomVariableGroups.Add(cvg);
}
这样做:
foreach(var cvg in CustomVariableGroups.Where( x => x.Disabled))
{
CustomVariableGroups.Remove(cvg);
}
如果这不起作用(取决于Enumerable.Where使用迭代器块,我认为),你可以这样做:
foreach(var cvg in Custom VariableGroups.Where( x=> x.Disabled).ToList())
{
CustomVariableGroups.Remove(cvg);
}