C# 如何添加到ObservableCollection<;T>;Getter中具有LINQ Where()的项?
我最近在我的一个域实体中添加了一个禁用的属性。我有一个视图模型中这些实体的C# 如何添加到ObservableCollection<;T>;Getter中具有LINQ Where()的项?,c#,linq,mvvm,C#,Linq,Mvvm,我最近在我的一个域实体中添加了一个禁用的属性。我有一个视图模型中这些实体的列表。我刚刚更改了getter,根据UI设置筛选列表,以选择性地显示禁用的项 public ObservableCollection<CustomVariableGroup> CustomVariableGroups { get { if (this.ShowDisabled) { return this._customVariableGroups; } ret
列表。我刚刚更改了getter,根据UI设置筛选列表,以选择性地显示禁用的项
public ObservableCollection<CustomVariableGroup> CustomVariableGroups
{
get
{
if (this.ShowDisabled) { return this._customVariableGroups; }
return new ObservableCollection<CustomVariableGroup>(this._customVariableGroups.Where(x => x.Disabled == false));
}
}
我想我知道为什么了:newGroup被添加到了新的ObservableCollection
,而不是customVariableGroups的backing字段
如果LINQ Where()扩展方法能够返回ObservableCollection
(私有支持字段本身的类型)而不是IEnumerable,我想我不会有这个问题。现在,由于Where()返回IEnumerable
,因此我需要将其包装在一个新的ObservableCollection
中
在同一视图模型中添加新项的正确/最佳方法是什么?我是否需要将其直接添加到私人支持字段?我不想这样做,因为我不想记住不要使用属性本身。我会维护您的支持列表,然后为您的ObservableCollection提出更改的属性
this.CustomVariableGroups.Add(newGroup);
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);
PublicObservableCollection CustomVariableGroup
{
得到
{
如果(this.ShowDisabled){返回此。_customVariableGroups;}
返回新的observeCollection(this._customVariableGroups.Where(x=>x.Disabled==false));
}
}
//添加到支持列表,但在要重建的属性上引发
//返回ObservableCollection
public void AddCustomVariableGroup(CustomVariableGroup newGroup)
{
此.\u customVariableGroups.Add(新组);
OnPropertyChanged(“CustomVariableGroup”);
}
//示例调用
AddCustomVariableGroup(新组);
我在WinPhone应用程序中显示过滤结果时遇到了类似的问题。我的解决方案是绑定到“ShowDisabled”属性更改,在这个事件中,只需Clear()
,并将内容读入主要可观察对象:本例中的CustomVariableGroup。大概是这样的:
public bool ShowDisabled
{
get
{
return showDisabled;
}
set
{
if (showDisabled!= value)
{
showDisabled = value;
NotifyPropertyChanged("ShowDisabled");
}
}
}
在构造函数中添加以下内容:this.PropertyChanged+=newpropertychangedventhandler(MyViewModel\u 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);
}
}
}
绑定到CustomVariableGroup
的组件应相应更新
免责声明:当然,这会对性能产生影响,您需要确定它是否可以忽略。我会做一些类似@Tallmaris的事情,但在MyViewModel\u 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);
}
如果这不起作用(取决于是否可枚举。我认为哪里使用迭代器块),您可以这样做:
foreach(var cvg in Custom VariableGroups.Where( x=> x.Disabled).ToList())
{
CustomVariableGroups.Remove(cvg);
}
您可以绑定到ICollectionView并在禁用的属性中设置筛选器,而不是直接绑定到集合。无需更改源集合
this.CustomVariableGroups.Add(newGroup);
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);
编辑:
视图模型:
//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"); }
}
//此集合只初始化一次-例如,在ctor中,使用add、remove、clear to alter
public ObservableCollection CustomVariableGroups{get;private set;}
//在ctor中只创建一次
公共ICollectionView MyView{get;private set;}
//执行器
this.CustomVariableGroups=新的ObservableCollection();
this.MyView=CollectionViewSource.GetDefaultView(this.CustomVariableGroups);
//在禁用的属性中,设置过滤器
公共图书馆
{
获取{return\u showDisabled;}
集合{
_showDisabled=值;
如果(_showDisabled)
//显示刚刚被禁用
this.MyView.Filter=(项目)=>
{
var myitem=(CustomVariableGroup)项;
返回myitem.Disabled;
};
其他的
{
//全部展示
this.MyView.Filter=(项)=>{return true;};
}
this.NotifyPropertyChanged(“ShowDisabled”);}
}
xaml
这在我的测试项目中起作用正如评论中提到的,解决这一问题的正确方法是在视图中,而不是在视图模型中。这只是一个视图问题。我想我应该发布我是如何处理的,以防万一这对其他人有帮助
首先,getter(视图模型)每次都应该返回完整列表:
public ObservableCollection<CustomVariableGroup> CustomVariableGroups
{ get { return this._customVariableGroups; } }
然后,在代码隐藏中,我实现了过滤器:
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并试图避免类背后的代码。但是,拥有它比破解视图模型要好。这就是我寻求帮助的原因,巴德。与其说它是坏的,你能建议如何使它正确吗?每次你调用你的属性时,都会创建一个新的可观察集合……在更高的级别上,代码this.CustomVariableGroups.Add(newGroup)在哪里代码>定位?您应该创建一次可观察的集合,并以某种方式同步这两个列表。CustomVariableGroup的类型是什么?您不能简单地创建一个集合源,并对该属性进行筛选吗?该代码位于同一视图模型类中,当用户想要添加新组时,会调用它。CustomVariableGroups的类型为ObservableCollection
,如上面的代码所示。@SteveB我认为您给出了正确的答案:使用此属性上的筛选器创建一个集合源。视图模型代码不应根据视图想要过滤的内容进行更改。如果是视图问题,则应在视图中处理。这不起作用。通过在执行Linq查询之前清除集合,您正在查询一个空集合。哎哟,对不起,我只是从现有代码复制和粘贴并更改名称。当然,他需要从始终包含所有元素的支持属性进行查询,或者在清除集合之前进行查询,然后添加。我编辑了答案。@Tallmaris谢谢,但这看起来更像是
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;
}