Фильтрация записей в DataPresenter - это всего лишь средство фильтрации записей на основе определенных критериев. Обычно этот критерий предоставляется с помощью одного из встроенных пользовательских интерфейсов - либо с помощью LabelIcons , который представляет собой просто раскрывающийся список отфильтрованных значений, либо с помощью FilterRecord , который представляет собой специальную специальную запись. это отображается с ячейками для каждого столбца, чтобы позволить выбрать / ввести оператор и значение.
При этом фильтрацией записей можно манипулировать в коде, если хотите. FieldLayout предоставляет коллекцию RecordFilters , где RecordFilter предоставляет условия (то есть критерии соответствия) и поле, для которого должно быть выполнено сравнение. Он также отображается в RecordManager , но это действительно облегчает фильтрацию в иерархических ситуациях, когда критерии фильтрации различны для каждого «острова» дочерних записей.
Поскольку вы хотите искать несколько полей по одним и тем же критериям, вам нужно будет создать RecordFilter для каждого Поле в коллекции Поля FieldLayout (или любое подмножество полей, к которому вы хотите применить это). Поскольку вы хотите выполнить текстовый поиск, вы, вероятно, захотите использовать ComparisonCondition, где используемый вами ComparisonOperator - Contains, а значением будет текст для поиска. Теперь, так как вы хотите, чтобы запись соответствовала, если значение найдено в любом из полей (для которых вы создали RecordFilter), вам также нужно будет установить свойство FieldLayoutSettings * RecordFiltersLogicalOperator на Или (по умолчанию это разрешается на А, поскольку обычно требуется сопоставить запись, когда все критерии соответствуют введенным значениям).
Таким образом, ниже приведено базовое присоединенное поведение (в данном случае свойство с именем FilterText , которое вы бы указали в DataPresenter для фильтрации). Это поведение / свойство будет манипулировать RecordFilters элемента DefaultFieldLayout с учетом текстового значения свойства FilterText.
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 к этому присоединенному свойству. Обратите внимание, что вам нужно будет определить отображение xmlns для local как пространства имен 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, потому что этот элемент будет манипулировать Inlines of TextBlock, и это будет устанавливать свойство 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>