本当に主題はそれをすべて言います。
<CollectionViewSource x:Key="MyData"
Source="{Binding}" Filter="{ SomethingMagicInXaml? }" />
コードを後回しにできないわけではありません。それはただ私をしつこくします。
本当に主題はそれをすべて言います。
<CollectionViewSource x:Key="MyData"
Source="{Binding}" Filter="{ SomethingMagicInXaml? }" />
コードを後回しにできないわけではありません。それはただ私をしつこくします。
XAML では、プログラム全体を作成するまで、「十分に努力」すれば、ほとんど何でも行うことができます。
コード ビハインドを回避することはありません (ライブラリを使用する場合、ライブラリを作成する必要はありませんが、アプリケーションはもちろんライブラリに依存しています)。この特定のケースで実行できることの例を次に示します。
<CollectionViewSource x:Key="Filtered" Source="{Binding DpData}"
xmlns:me="clr-namespace:Test.MarkupExtensions">
<CollectionViewSource.Filter>
<me:Filter>
<me:PropertyFilter PropertyName="Name" Value="Skeet" />
</me:Filter>
</CollectionViewSource.Filter>
</CollectionViewSource>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Markup;
using System.Windows.Data;
using System.Collections.ObjectModel;
using System.Windows;
using System.Text.RegularExpressions;
namespace Test.MarkupExtensions
{
[ContentProperty("Filters")]
class FilterExtension : MarkupExtension
{
private readonly Collection<IFilter> _filters = new Collection<IFilter>();
public ICollection<IFilter> Filters { get { return _filters; } }
public override object ProvideValue(IServiceProvider serviceProvider)
{
return new FilterEventHandler((s, e) =>
{
foreach (var filter in Filters)
{
var res = filter.Filter(e.Item);
if (!res)
{
e.Accepted = false;
return;
}
}
e.Accepted = true;
});
}
}
public interface IFilter
{
bool Filter(object item);
}
// Sketchy Example Filter
public class PropertyFilter : DependencyObject, IFilter
{
public static readonly DependencyProperty PropertyNameProperty =
DependencyProperty.Register("PropertyName", typeof(string), typeof(PropertyFilter), new UIPropertyMetadata(null));
public string PropertyName
{
get { return (string)GetValue(PropertyNameProperty); }
set { SetValue(PropertyNameProperty, value); }
}
public static readonly DependencyProperty ValueProperty =
DependencyProperty.Register("Value", typeof(object), typeof(PropertyFilter), new UIPropertyMetadata(null));
public object Value
{
get { return (object)GetValue(ValueProperty); }
set { SetValue(ValueProperty, value); }
}
public static readonly DependencyProperty RegexPatternProperty =
DependencyProperty.Register("RegexPattern", typeof(string), typeof(PropertyFilter), new UIPropertyMetadata(null));
public string RegexPattern
{
get { return (string)GetValue(RegexPatternProperty); }
set { SetValue(RegexPatternProperty, value); }
}
public bool Filter(object item)
{
var type = item.GetType();
var itemValue = type.GetProperty(PropertyName).GetValue(item, null);
if (RegexPattern == null)
{
return (object.Equals(itemValue, Value));
}
else
{
if (itemValue is string == false)
{
throw new Exception("Cannot match non-string with regex.");
}
else
{
return Regex.Match((string)itemValue, RegexPattern).Success;
}
}
}
}
}
XAML で何かをしたい場合、マークアップ拡張機能はあなたの味方です。
(拡張機能の名前を綴りたいと思うかもしれません。つまりme:FilterExtension
、Visual Studio のオンザフライ チェックで理由もなくエラーが発生する可能性があるため、もちろんコンパイルして実行しますが、警告が煩わしいかもしれません
。CollectionViewSource.Filter
IntelliSense に表示される場合、XML-element-notation を介してそのハンドラーを設定する必要はありません)
実際には、インスタンスにアクセスする必要さえありませんCollectionViewSource
。ViewModel でソース コレクションを直接フィルタリングできます。
ICollectionView view = CollectionViewSource.GetDefaultView(collection);
view.Filter = predicate;
ICollectionView.Filter
( のようなイベントではなく、CollectionViewSource.Filter
type のプロパティであることに注意してくださいPredicate<object>
)