C# 筛选多列ListView C WPF
我想用多列和多个过滤器过滤我的ListView,但我不知道如何 这是我的想法:一个窗口显示当前选定的 列标题,您可以在下拉列表中选择=或>,然后根据您的条件进行筛选,我只找到一列的解决方案,但不知道如何进行多重筛选 数据加载:C# 筛选多列ListView C WPF,c#,wpf,C#,Wpf,我想用多列和多个过滤器过滤我的ListView,但我不知道如何 这是我的想法:一个窗口显示当前选定的 列标题,您可以在下拉列表中选择=或>,然后根据您的条件进行筛选,我只找到一列的解决方案,但不知道如何进行多重筛选 数据加载: var xdoc = XDocument.Load(@"C:\temp\webTsl.xml"); var units = from u in xdoc.Descendants("sl")
var xdoc = XDocument.Load(@"C:\temp\webTsl.xml");
var units = from u in xdoc.Descendants("sl")
select new
{
EQNr = (string)u.Element("id"),
//EQCore = (string)u.Element(""),
ArtNr = (string)u.Element("artNr"),
Bez = (string)u.Element("bez"),
//KundenBez = (string)u.Element(""),
//ProjektNr = (string)u.Element(""),
//LiefDat = (DateTime)u.Element(""),
//EqStart = (DateTime)u.Element(""),
//GewaehrStart = (DateTime)u.Element(""),
//GewaehrEnde = (DateTime)u.Element("")
};
foreach (var unit in units)
{
items.Add(new Anlagen(unit.EQNr, unit.ArtNr, unit.Bez));
}
ListViewAnlagen.ItemsSource = CollectionViewSource.GetDefaultView(items);
类别:
public virtual string EQNr { get; set; }
//public virtual string EQCore { get; set; }
public virtual string ArtNr { get; set; }
public virtual string Bez { get; set; }
//public virtual string KundenBez { get; set; }
//public virtual string ProjektNr { get; set; }
//public virtual DateTime? LiefDat { get; set; }
//public virtual DateTime? EqStart { get; set; }
//public virtual DateTime? GewaehrStart { get; set; }
//public virtual DateTime? GewaehrEnde { get; set; }
public Anlagen(string eqNr,string artNr, string bez) /*, DateTime liefdat, DateTime inbetnahme,DateTime garantiestart,DateTime garantieende*/
{
this.EQNr = eqNr;
//this.EQCore = eqCore;
this.ArtNr = artNr;
this.Bez = bez;
//this.KundenBez = kundenBez;
//this.ProjektNr = projektNr;
//this.LiefDat = liefDat;
//this.EqStart = eqStart;
//this.GewaehrStart = gewaehrStart;
//this.GewaehrEnde = gewaehrEnde;
}
public Anlagen()
{
}
基本上,您需要一个过滤器定义,其中传递项目,并使用特定于列的过滤器函数确定项目是否满足过滤器的要求 假设您有一个过滤器界面,如下所示:
public interface IFilterBase<TItem>
{
PropertyInfo Property { get; } // can be used to display the property name etc.
bool ApplyFilter(T value);
}
为了使MVVM准备好过滤项集合,我在我的一个项目中使用了以下帮助器类:
public class ObservableLinq<TIn, TOut> : IEnumerable<TOut>, INotifyCollectionChanged
{
private ObservableCollection<TIn> _Source;
private Func<IEnumerable<TIn>, IEnumerable<TOut>> _Transformation;
public ObservableLinq(ObservableCollection<TIn> source, Func<IEnumerable<TIn>, IEnumerable<TOut>> transformation)
{
_Source = source;
_Transformation = transformation;
_Source.CollectionChanged += Source_CollectionChanged;
}
public ObservableLinq(IEnumerable<TIn> source, Func<IEnumerable<TIn>, IEnumerable<TOut>> transformation)
: this(source as ObservableCollection<TIn> ?? new ObservableCollection<TIn>(source), transformation)
{
}
private void Source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
RaiseCollectionChanged();
}
public IEnumerator<TOut> GetEnumerator()
{
return _Transformation(_Source).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
// could be a property as well, but this empathizes, that the source collection is not the primary functionality here
public ObservableCollection<TIn> GetSourceCollection()
{
return _Source;
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected void RaiseCollectionChanged()
{
var handler = CollectionChanged;
if (handler != null)
{
// always reset as it would be pretty complicated to track the actual changes across all the linq thingies
handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
/// <summary>
/// Call when a filter relevant property changed on source collection entries
/// </summary>
public void CollectionChangedNeeded()
{
RaiseCollectionChanged();
}
}
我觉得这种方法比WPF提供的控件的内置过滤器功能更灵活。基于正则表达式的过滤器,自定义属性类型的过滤器。。。所有这些都是可能的,每种类型的过滤器都不费吹灰之力。只是过滤基础设施的初始设置并不是很简单。我可以问你一个例子吗?先生,我试图理解你的解决方案,但我真的不明白,你可以举个例子吗?也许我可以稍后再写,而不是现在。。。从代码片段中可以看到,一个现成的示例需要几行代码和xaml。
ObservableCollection<IFilterBase<TItem>> Filters;
source.Where(item => Filters.All(filter => filter.ApplyFilter(item)))
public class ObservableLinq<TIn, TOut> : IEnumerable<TOut>, INotifyCollectionChanged
{
private ObservableCollection<TIn> _Source;
private Func<IEnumerable<TIn>, IEnumerable<TOut>> _Transformation;
public ObservableLinq(ObservableCollection<TIn> source, Func<IEnumerable<TIn>, IEnumerable<TOut>> transformation)
{
_Source = source;
_Transformation = transformation;
_Source.CollectionChanged += Source_CollectionChanged;
}
public ObservableLinq(IEnumerable<TIn> source, Func<IEnumerable<TIn>, IEnumerable<TOut>> transformation)
: this(source as ObservableCollection<TIn> ?? new ObservableCollection<TIn>(source), transformation)
{
}
private void Source_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
RaiseCollectionChanged();
}
public IEnumerator<TOut> GetEnumerator()
{
return _Transformation(_Source).GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
// could be a property as well, but this empathizes, that the source collection is not the primary functionality here
public ObservableCollection<TIn> GetSourceCollection()
{
return _Source;
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
protected void RaiseCollectionChanged()
{
var handler = CollectionChanged;
if (handler != null)
{
// always reset as it would be pretty complicated to track the actual changes across all the linq thingies
handler(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
/// <summary>
/// Call when a filter relevant property changed on source collection entries
/// </summary>
public void CollectionChangedNeeded()
{
RaiseCollectionChanged();
}
}
public ObservableLinq<TItem, TItem> FilteredItems { get {...} set {...} }
// init:
FilteredItems = new ObservableLinq<TItem, TItem>(ItemsList, source.Where(item => Filters.All(filter => filter.ApplyFilter(item))));
FilteredItems.CollectionChangedNeeded();