Kev*_*vin 3 wpf infragistics xamdatagrid
我试图在XamDataGrid上实现搜索(Ctrl + F)功能.如何以编程方式在网格上调用记录筛选,搜索多列中的内容并仅显示与搜索匹配的列?
小智 9
DataPresenter中的记录过滤就是这样 - 根据某些指定的标准过滤记录的方法.通常,标准是通过其中一个内置的ui提供的 - 使用LabelIcons,它只是过滤值的下拉列表,或者通过FilterRecord,这是一个专用的特殊记录,显示每列的单元格以允许选择/进入运营商和价值.
也就是说,如果您愿意,可以在代码中操作记录过滤.所述FieldLayout暴露出RecordFilters集合,其中一个RecordFilter的提供了条件(即,匹配标准)和所述匹配应该执行领域.它也暴露在RecordManager之外,但这实际上是为了便于在分层情况下进行过滤,其中过滤条件对于子记录的每个"孤岛"是不同的.
由于您要搜索多个字段以获得相同的条件,因此您需要为FieldLayout的Fields集合中的每个Field创建一个RecordFilter(或者您希望将其应用到的Fields的任何子集).由于您要进行文本搜索,因此您可能希望使用比较条件,其中您使用的ComparisonOperator是包含的,值将是要搜索的文本.现在,因为如果在任何字段(您已为其创建了RecordFilter)中找到值,您希望匹配记录,您还需要将FieldLayoutSettings的RecordFiltersLogicalOperator属性设置为Or(默认情况下,这会解析为And,因为想要在所有条件与输入的值匹配时匹配记录.
因此,为此目的,以下是一个基本的附加行为(在这种情况下,您将在要过滤的DataPresenter上设置名为FilterText的属性).考虑到FilterText属性的文本值,此行为/属性将操作DefaultFieldLayout的RecordFilters.
public static class DataPresenterHelpers
{
#region FilterText
/// <summary>
/// FilterText Attached Dependency Property
/// </summary>
public static readonly DependencyProperty FilterTextProperty =
DependencyProperty.RegisterAttached("FilterText", typeof(string), typeof(DataPresenterHelpers),
new FrameworkPropertyMetadata((string)null,
new PropertyChangedCallback(OnFilterTextChanged)));
/// <summary>
/// Gets the text to be used to filter the DataPresenter on which the property was set.
/// </summary>
public static string GetFilterText(DependencyObject d)
{
return (string)d.GetValue(FilterTextProperty);
}
/// <summary>
/// Sets the filter text on the DataPresenter that should be used to manipulate the RecordFilters of the specified DataPresenter
/// </summary>
public static void SetFilterText(DependencyObject d, string value)
{
d.SetValue(FilterTextProperty, value);
}
/// <summary>
/// Handles changes to the FilterText property.
/// </summary>
private static void OnFilterTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var dp = d as DataPresenterBase;
if (dp.DefaultFieldLayout != null)
{
dp.DefaultFieldLayout.RecordFilters.Clear();
dp.DefaultFieldLayout.Settings.RecordFiltersLogicalOperator = LogicalOperator.Or;
foreach (var field in dp.DefaultFieldLayout.Fields)
{
var filter = new RecordFilter();
filter.Field = field;
filter.Conditions.Add(new ComparisonCondition(ComparisonOperator.Contains, e.NewValue));
dp.DefaultFieldLayout.RecordFilters.Add(filter);
}
}
}
#endregion //FilterText
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以执行以下操作,将TextBox的值连接到此附加属性.注意,您需要将local的xmlns映射定义为您将上述类放入的任何clr命名空间.
<TextBox DockPanel.Dock="Top" x:Name="txtFilter" />
<igDP:XamDataGrid
x:Name="grid"
BindToSampleData="True"
local:DataPresenterHelpers.FilterText="{Binding ElementName=txtFilter, Path=Text}">
</igDP:XamDataGrid>
Run Code Online (Sandbox Code Playgroud)
现在问题的另一部分是仅显示包含匹配值的列.作为记录过滤器本身的一部分,这实际上是不可能的,因为记录过滤是基于某些指定的标准过滤掉记录,并且与隐藏/显示列/字段无关.也就是说,也许一种方法可以帮助最终用户理解匹配文本所在的位置,以突出显示单元格内的文本.
为了提供这样的功能,我定义了一个名为HighlightTextBlock的派生TextBlock .它暴露了几个属性:
这是该类的代码:
public class HighlightTextBlock
: TextBlock
{
#region Member Variables
private DispatcherOperation _pendingUpdate;
#endregion //Member Variables
#region Constructor
static HighlightTextBlock()
{
}
/// <summary>
/// Initializes a new <see cref="HighlightTextBlock"/>
/// </summary>
public HighlightTextBlock()
{
}
#endregion //Constructor
#region Base class overrides
#region OnInitialized
protected override void OnInitialized(EventArgs e)
{
if (_pendingUpdate != null)
this.UpdateInlines(null);
base.OnInitialized(e);
}
#endregion //OnInitialized
#endregion //Base class overrides
#region Properties
#region FilterText
/// <summary>
/// Identifies the <see cref="FilterText"/> dependency property
/// </summary>
public static readonly DependencyProperty FilterTextProperty = DependencyProperty.Register("FilterText",
typeof(string), typeof(HighlightTextBlock), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnCriteriaChanged)));
/// <summary>
/// Returns or sets the text that should be highlighted
/// </summary>
/// <seealso cref="FilterTextProperty"/>
[Description("Returns or sets the text that should be highlighted")]
[Category("Behavior")]
[Bindable(true)]
public string FilterText
{
get
{
return (string)this.GetValue(HighlightTextBlock.FilterTextProperty);
}
set
{
this.SetValue(HighlightTextBlock.FilterTextProperty, value);
}
}
#endregion //FilterText
#region FilterTextBackground
/// <summary>
/// Identifies the <see cref="FilterTextBackground"/> dependency property
/// </summary>
public static readonly DependencyProperty FilterTextBackgroundProperty = DependencyProperty.Register("FilterTextBackground",
typeof(Brush), typeof(HighlightTextBlock), new FrameworkPropertyMetadata(Brushes.Yellow, new PropertyChangedCallback(OnCriteriaChanged)));
/// <summary>
/// Returns or sets the background of the matching text.
/// </summary>
/// <seealso cref="FilterTextBackgroundProperty"/>
[Description("Returns or sets the background of the matching text.")]
[Category("Behavior")]
[Bindable(true)]
public Brush FilterTextBackground
{
get
{
return (Brush)this.GetValue(HighlightTextBlock.FilterTextBackgroundProperty);
}
set
{
this.SetValue(HighlightTextBlock.FilterTextBackgroundProperty, value);
}
}
#endregion //FilterTextBackground
#region FilterTextComparisonType
/// <summary>
/// Identifies the <see cref="FilterTextComparisonType"/> dependency property
/// </summary>
public static readonly DependencyProperty FilterTextComparisonTypeProperty = DependencyProperty.Register("FilterTextComparisonType",
typeof(StringComparison), typeof(HighlightTextBlock), new FrameworkPropertyMetadata(StringComparison.CurrentCultureIgnoreCase, new PropertyChangedCallback(OnCriteriaChanged)));
/// <summary>
/// Returns or sets the StringComparison when locating the FilterText within the RawText.
/// </summary>
/// <seealso cref="FilterTextComparisonTypeProperty"/>
[Description("Returns or sets the StringComparison when locating the FilterText within the RawText.")]
[Category("Behavior")]
[Bindable(true)]
public StringComparison FilterTextComparisonType
{
get
{
return (StringComparison)this.GetValue(HighlightTextBlock.FilterTextComparisonTypeProperty);
}
set
{
this.SetValue(HighlightTextBlock.FilterTextComparisonTypeProperty, value);
}
}
#endregion //FilterTextComparisonType
#region FilterTextForeground
/// <summary>
/// Identifies the <see cref="FilterTextForeground"/> dependency property
/// </summary>
public static readonly DependencyProperty FilterTextForegroundProperty = DependencyProperty.Register("FilterTextForeground",
typeof(Brush), typeof(HighlightTextBlock), new FrameworkPropertyMetadata(Brushes.Black, new PropertyChangedCallback(OnCriteriaChanged)));
/// <summary>
/// Returns or sets the brushed used for the foreground of the matching text.
/// </summary>
/// <seealso cref="FilterTextForegroundProperty"/>
[Description("Returns or sets the brushed used for the foreground of the matching text.")]
[Category("Behavior")]
[Bindable(true)]
public Brush FilterTextForeground
{
get
{
return (Brush)this.GetValue(HighlightTextBlock.FilterTextForegroundProperty);
}
set
{
this.SetValue(HighlightTextBlock.FilterTextForegroundProperty, value);
}
}
#endregion //FilterTextForeground
#region RawText
/// <summary>
/// Identifies the <see cref="RawText"/> dependency property
/// </summary>
public static readonly DependencyProperty RawTextProperty = DependencyProperty.Register("RawText",
typeof(string), typeof(HighlightTextBlock), new FrameworkPropertyMetadata(null, new PropertyChangedCallback(OnCriteriaChanged)));
/// <summary>
/// Returns or sets the base string that will be displayed by the element.
/// </summary>
/// <seealso cref="RawTextProperty"/>
[Description("Returns or sets the base string that will be displayed by the element.")]
[Category("Behavior")]
[Bindable(true)]
public string RawText
{
get
{
return (string)this.GetValue(HighlightTextBlock.RawTextProperty);
}
set
{
this.SetValue(HighlightTextBlock.RawTextProperty, value);
}
}
#endregion //RawText
#endregion //Properties
#region Methods
#region OnCriteriaChanged
private static void OnCriteriaChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = d as HighlightTextBlock;
if (instance._pendingUpdate == null)
{
instance._pendingUpdate = instance.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new SendOrPostCallback(instance.UpdateInlines), new object[] { null });
}
}
#endregion //OnCriteriaChanged
#region UpdateInlines
private void UpdateInlines(object param)
{
_pendingUpdate = null;
string filterText = this.FilterText;
string text = this.RawText;
var inlines = this.Inlines;
try
{
inlines.Clear();
if (string.IsNullOrEmpty(filterText))
{
inlines.Add(text);
return;
}
var foreground = this.FilterTextForeground;
var background = this.FilterTextBackground;
var comparison = this.FilterTextComparisonType;
var newInlines = new List<Inline>();
int filterTextLen = filterText.Length;
int start = 0;
do
{
int end = text.IndexOf(filterText, start, comparison);
string substr = text.Substring(start, (end < 0 ? text.Length : end) - start);
newInlines.Add(new Run(substr));
if (end < 0)
break;
var run = new Run(text.Substring(end, filterTextLen));
// note we could bind and not rebuild when the background/foreground
// changes but that doesn't seem likely to happen and would add more
// overhead than just referencing the value directly
if (null != foreground)
run.Foreground = foreground;
if (null != background)
run.Background = background;
newInlines.Add(run);
start = end + filterTextLen;
} while (true);
inlines.AddRange(newInlines);
}
finally
{
if (_pendingUpdate != null)
{
_pendingUpdate.Abort();
_pendingUpdate = null;
}
}
}
#endregion //UpdateInlines
#endregion //Methods
}
Run Code Online (Sandbox Code Playgroud)
那么您可以更改用于在其渲染模板中使用它的编辑器的模板.例如
<Window x:Class="WpfApplication6.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:igDP="http://infragistics.com/DataPresenter"
xmlns:igEditors="http://infragistics.com/Editors"
xmlns:local="clr-namespace:WpfApplication6"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<TextBox DockPanel.Dock="Top" x:Name="txtFilter" />
<igDP:XamDataGrid
x:Name="grid"
BindToSampleData="True"
local:DataPresenterHelpers.FilterText="{Binding ElementName=txtFilter, Path=Text}">
<igDP:XamDataGrid.Resources>
<Style TargetType="igEditors:XamTextEditor">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="igEditors:XamTextEditor">
<Border x:Name="MainBorder"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
>
<local:HighlightTextBlock
Margin="{TemplateBinding Padding}"
FilterText="{Binding Path=Host.DataPresenter.(local:DataPresenterHelpers.FilterText), RelativeSource={RelativeSource TemplatedParent}}"
RawText="{TemplateBinding DisplayText}"
TextWrapping="{TemplateBinding TextWrapping}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
TextAlignment="{TemplateBinding TextAlignmentResolved}"
/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</igDP:XamDataGrid.Resources>
</igDP:XamDataGrid>
</DockPanel>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
5166 次 |
最近记录: |