gpt4 book ai didi

wpf - 如何实现在XamDataGrid中导致多列记录过滤的搜索?

转载 作者:行者123 更新时间:2023-12-01 08:17:19 27 4
gpt4 key购买 nike

我正在尝试在XamDataGrid上实现搜索(Ctrl + F)功能。如何在网格上以编程方式调用记录过滤,以跨多个列搜索内容并仅显示与搜索匹配的列?

最佳答案

DataPresenter 中的记录过滤就是这样-一种基于某些指定条件过滤记录的方法。通常,通过内置ui之一提供标准-使用 LabelIcons (仅是过滤值的下拉列表),或者通过 FilterRecord (专用的特殊记录,使用每列的单元格显示)来提供标准。允许选择/输入运算符和值。

话虽如此,如果您愿意,可以使用代码来操纵记录过滤。 FieldLayout 公开一个 RecordFilters 集合,其中RecordFilter提供条件(即匹配条件)和应执行匹配的字段。它还在 RecordManager 之外公开,但这确实有助于在分层情况下进行过滤,在这种情况下,子记录的每个“岛”的过滤条件都不同。

由于要在多个字段中搜索相同的条件,因此需要为FieldLayout的字段集合(或要将其应用到的字段的任何子集)中的每个字段创建一个 RecordFilter 。由于您要进行文本搜索,因此您可能希望使用CompareCondition,其中您使用的CompareOperator为Contains,并且值将为要搜索的文本。现在,如果您希望在任何字段(已为其创建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的值连接到此附加属性。注意,您需要为本地定义一个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的Inlines,并且将设置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>

    关于wpf - 如何实现在XamDataGrid中导致多列记录过滤的搜索?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7854570/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com