我想在XamDataGrid上实现一个搜索(Ctrl + F)功能。如何以编程方式在网格上调用记录过滤,以跨多列中的内容进行搜索并仅显示与搜索匹配的列?如何实现在XamDataGrid中导致多列记录过滤的搜索?
回答
DataPresenter中的记录筛选就是这样 - 根据某些指定条件过滤记录的方法。通常,标准是通过内置的UI之一提供的 - 要么使用LabelIcons(这只是已过滤值的下拉列表),要么通过FilterRecord这是一个专用的特殊记录,显示每列的单元格以允许选择/输入运营商和价值。
如此说来记录过滤可以在代码中,如果你想进行操作。所述FieldLayout暴露出RecordFilters集合,其中一个RecordFilter的提供条件(即匹配标准)和所述匹配应该执行领域。它也暴露在RecordManager但这实际上是为了便于在分层情况下过滤,其中过滤标准对于子记录的每个“岛”都是不同的。
既然你想搜索多个字段相同的标准,你就需要在FieldLayout的领域创造一个RecordFilter的每个现场集合(或任何你想要的字段的子集到这被应用)。由于您想要进行文本搜索,因此您可能希望在使用ComparisonOperator的Contains中使用ComparisonCondition,并且该值将是要搜索的文本。现在既然你想要一个记录匹配,如果在任何一个字段中找到该值(为此你创建了一个RecordFilter),你还需要将FieldLayoutSettings'RecordFiltersLogicalOperator属性设置为或(默认情况下这将解决为并且因为当所有标准匹配输入的值时通常都希望匹配记录)。
因此,为此目的,下面是一个基本的附加行为(在这种情况下,您将在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
}
然后,您可以执行如下操作,将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>
现在问题的另一部分是关于只显示包含匹配值的列。由于记录过滤是根据某些指定的标准过滤掉记录,并且与隐藏/显示列/字段无关,所以这不是真正可以作为记录过滤器本身的一部分。也就是说,可能帮助最终用户了解匹配文本所在位置的一种方法是突出显示单元格内的文本。
为了提供这样的功能,我定义了派生的TextBlock,名为HighlightTextBlock。它暴露了几个属性:
- RawText - 这是将要显示的源文本。它不能使用Text属性,因为这个元素将操纵TextBlock的Inline,并且将设置Text属性,在双向绑定的情况下,它将在单向绑定或将值推回到源的情况下破坏绑定。
- FilterText - 用于指示要在RawText中查找的文本。
- FilterTextComparisonType - 用于指示匹配的字符串比较(即区分大小写等)。
- FilterTextForeground - 用于突出显示匹配文本的前景。
- FilterTextBackground - 用于突出显示匹配文本的背景。
下面是类代码:
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
}
,那么你可以改变你使用他们的渲染模板用这个编辑模板。例如
<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>
,我会解决这个问题。将代码添加到搜索按钮单击事件(或其他触发机制),并直接在代码中执行搜索,使用LINQ或记录被记录比较,无论在效果最好的方式你的情况(这将有助于知道如何填充列和行)。
一旦你有一组记录和/或具有相应结果列,隐瞒没有命中列。为了简化流程,我将创建一个应该隐藏的列集合,然后有一个处理每列的方法。该方法将搜索列数据,并在第一个匹配的符号处,从将要隐藏的列列表中移除列,并停止处理列中的记录。
在过程结束时,列表将包含列隐藏起来,然后你可以用它来执行实际隐藏的名单。
这种机制还可以扩展到隐藏没有任何匹配行,假设有多个行。我会通过在处理第一列时隐藏每个没有匹配的行并支持这一点,然后在发现匹配的后续列中取消隐藏它们。
谢谢你的分享。我也会分享。 我用这个例子来处理一个更简单的情况。 我只是想在一列上设置一个过滤器。 这就是:
Imports Infragistics.Windows.DataPresenter
Imports Infragistics.Windows.Controls
Public Class DataPresenterFilter
Public Shared Function GetTitleFilter(ByVal element As DependencyObject) As String
If element Is Nothing Then
Throw New ArgumentNullException("element")
End If
Return element.GetValue(TitleFilter)
End Function
Public Shared Sub SetTitleFilter(ByVal element As DependencyObject,
ByVal value As String)
If element Is Nothing Then
Throw New ArgumentNullException("element")
End If
element.SetValue(TitleFilter, value)
End Sub
Public Shared ReadOnly TitleFilter As _
DependencyProperty = DependencyProperty.RegisterAttached("TitleFilter", _
GetType(String), GetType(DataPresenterFilter), _
New FrameworkPropertyMetadata(String.Empty,
New PropertyChangedCallback(AddressOf OnTitleFilterChanged)))
Private Shared Sub OnTitleFilterChanged(d As DependencyObject,
e As DependencyPropertyChangedEventArgs)
Dim dp As DataPresenterBase = CType(d, DataPresenterBase)
If (Not dp.DefaultFieldLayout Is Nothing) Then
Dim Filter As RecordFilter = New RecordFilter()
Filter.FieldName = "Title"
Filter.Conditions.Add(
New ComparisonCondition(ComparisonOperator.Contains, e.NewValue))
dp.DefaultFieldLayout.RecordFilters.Remove(
dp.DefaultFieldLayout.RecordFilters.Item("Title"))
dp.DefaultFieldLayout.RecordFilters.Add(Filter)
End If
End Sub
End Class
而XAML:
xmlns:Inv="clr-namespace:InventoryApp"
<TextBox Height="23" Margin="0,2,0,2" x:Name="tbTitle" />
<igDP:XamDataPresenter Name="xamDataPresenterPublicationCollection"
DataSource="{Binding Source={StaticResource PublicationCollectionViewSource},
UpdateSourceTrigger=PropertyChanged}" IsSynchronizedWithCurrentItem="True"
ActiveDataItem="{Binding Path=PublicationModel, Mode=OneWay}"
Inv:DataPresenterFilter.TitleFilter="{Binding ElementName=tbTitle, Path=Text}"/>
这完全适用于我。
我正在寻找一个非常基本的解决方案,所以我会分享一下为我工作的东西。这里是我的C#代码隐藏代码过滤器应用于列:
grdConnectionManagerEntries.FieldLayouts[0].RecordFilters.Clear(); // Clear any existing filters before applying this one.
grdConnectionManagerEntries.FieldLayouts[0].RecordFilters.Add(new RecordFilter(new Field("Name")));
grdConnectionManagerEntries.FieldLayouts[0].RecordFilters[0].Conditions.Add(new Infragistics.Windows.Controls.ComparisonCondition(Infragistics.Windows.Controls.ComparisonOperator.Contains, connectionName));
这里grdConnectionManagerEntries是我XamDataGrid,我有一个字段(即列)称为名称,而我加入包含筛选器,它将按给定的筛选连接名称。
由于某些原因,过滤器文本只在XamDataGrid的用户界面中显示,当我使用包含比较运算符;我猜是因为那是该列上的默认筛选器运算符。所以有些事情我做得不对,但是因为我想使用Contains运算符,所以它已经用于我的目的。
- 1. 如何实现过滤器搜索/列表视图搜索?
- 2. solr如何实现过滤器搜索
- 3. 在Android中实现搜索过滤器
- 4. xamDataGrid过滤器记录样式
- 5. Netsuite - 如何过滤多个记录上的物品搜索
- 6. 如何在Ionic中实现搜索和过滤
- 7. 如何在RecyclerView Android中实现搜索过滤器?
- 8. 过滤搜索管道实现
- 9. 如何在搜索表单中搜索多条记录?
- 10. 如何通过在javascript中搜索多个属性值来实现过滤器过滤器?
- 11. 如何使用任何过滤器选项搜索记录SOLR?
- 12. 如何过滤/搜索助手的列
- 13. Android如何实现可扩展的listview过滤器搜索?
- 14. 记录现场搜索错过
- 15. 过滤器在NHibernate的列中搜索
- 16. 在Django中实现过滤器/搜索的最佳方法
- 17. 如何使用全文搜索在多列上进行过滤
- 18. 如何实现弹性搜索而不是过滤?
- 19. 如何实现过滤器搜索使用Struts2 jquery插件
- 20. 如何实现动态分类/搜索过滤器
- 21. 如何使用Symfony2实现搜索过滤器表单
- 22. 如何在AngularJS中预过滤搜索
- 23. 如何搜索两列(其中一列仅出现在几条记录中)?
- 24. 如何加入记录的多次出现对主记录过滤
- 25. 使用搜索规范在Siebel的Pick Applet上过滤记录
- 26. 如何在多个过滤器的弹性搜索中应用分面搜索?
- 27. 多搜索过滤算法
- 28. 多表搜索过滤器
- 29. Pandas数据框记录过滤符号如何实现?
- 30. 如何在RoR中搜索记录?
假设所有的列都是DataGridTextColumns是否安全? – philt5252
不,他们不是,但访问字段的内容并不像访问代码中的记录过滤那样重要。 – Kevin