繁体   English   中英

根据来自多个 TextBoxes MVVM 的值过滤 WPF DataGrid (DataTable)

[英]Filter WPF DataGrid (DataTable) based on values from several TextBoxes MVVM

我一直在尝试设置基于 4 个文本框的过滤器。 如果第一个文本框不为空 -> 然后基于此进行过滤,如果第一个和第二个文本框不为空,则从这两个文本框中组合过滤器等。我希望我的过滤器像这样工作http://www.tablefilter.com/auto-过滤器.html

如您所见,我尝试了多种变体,但我不断收到下面提供的错误。 任何建议如何让它工作?

这是我的代码:

    public void EnableRowFiltering()
    {
        StringBuilder sb = new StringBuilder();

        if (this.YRNROSearchKey != string.Empty)
        {
            sb.Append($"YRNRO LIKE '%{this.YRNROSearchKey}%' AND ");
        }
        if (this.HAKUNIMISearchKey != string.Empty)
        {
            sb.Append($"HAKUNIMI LIKE '%{this.HAKUNIMISearchKey}%' AND ");
        }
        if (this.GROUPSearchKey != string.Empty)
        {
            sb.Append($"KONSERNI LIKE '%{this.GROUPSearchKey}%' AND ");
        }
        if (this.BUSINESSIDSearchKey != string.Empty)
        {
            sb.Append($"LY LIKE '%{this.BUSINESSIDSearchKey}%' AND ");
        }

        // I have tried also this way without success 
        // this.MainDataTable.DefaultView.RowFilter = YRNRO + HAKUNIMI + GROUP + BUSINESSID;
        string YRNRO = string.IsNullOrEmpty(this.YRNROSearchKey) ? "" : $"YRNRO LIKE '{this.YRNROSearchKey}*'";
        string HAKUNIMI = string.IsNullOrEmpty(this.HAKUNIMISearchKey) ? "" : $" AND HAKUNIMI LIKE '{this.HAKUNIMISearchKey}*'";
        string GROUP = string.IsNullOrEmpty(this.GROUPSearchKey) ? "" : $" AND KONSERNI LIKE '{this.GROUPSearchKey}*'";
        string BUSINESSID = string.IsNullOrEmpty(this.BUSINESSIDSearchKey) ? "" : $" AND LY LIKE '{this.BUSINESSIDSearchKey}*'";

        this.MainDataTable.DefaultView.RowFilter = sb.ToString();
    }

System.Data.SyntaxErrorException: '语法错误:'And' 运算符之后缺少操作数。'

这一直在工作,但我必须提供所有值(填写所有文本框)才能过滤:

  public void EnableRowFiltering()
  {
    this.MainDataTable.DefaultView.RowFilter = 
      $"YRNRO LIKE '{this.YRNROSearchKey}*' " + 
      $"OR HAKUNIMI LIKE '{this.HAKUNIMISearchKey}*'" +
      $"OR KONSERNI LIKE '{this.GROUPSearchKey}*'" +
      $"OR LY LIKE '{this.BUSINESSIDSearchKey}*'";
  }

我会选择 ReactiveExtensions(尤其是那些来自RxUI 的):

// written without IDE
var text1 = this.WhenAnyValue(x => x.YRNROSearchKey).Select(x => {
       if(string.IsNullOrEmpty(x))
          return null;
       return $"YRNRO LIKE '%{x}%";
     }); // get observable to monitor changes
var text2 = ...

var filterObservable = Observable.CombineLatest(
                new []{text1, text2, text3} , 
                    (textParts) => {
                         return string.Join(" AND ",  textParts.Where(x => !string.IsNullOrEmpty(x)));
                    }
             )
            .Throttle(TimeSpan.FromMilliseconds(80));

filterObservable.ObserveOnDispatcher().Subscribe(f => this.MainDataTable.DefaultView.RowFilter = f); 

我真的很喜欢 Rx,所以我会这样做 - 也许您可以将其用作模板并以其他方式解决更改通知,但构建过滤器应该可以工作。

RxUI 还带有 DyanmicData - 用于数据操作的优秀库,它基本上是可观察的 LINQ

您必须处理AND运算符。 您不能随时添加它,这取决于设置了多少条件(过滤器)。

假设定义一个名为int counter的变量在开始时设置为零,并在每次设置过滤器时增加并在每次清理过滤器时减少,您的代码应更改为:

public void EnableRowFiltering()
    {
        StringBuilder sb = new StringBuilder();
        var logicalOperator = counter > 0 ? " AND " : string.Empty;

        if (YRNROSearchKey != string.Empty)
        {
            logicalOperator = counter++ > 0 ? " AND " : string.Empty;
            sb.Append($"{logicalOperator}YRNRO LIKE '%{YRNROSearchKey}%'");
        }
        if (HAKUNIMISearchKey != string.Empty)
        {
            logicalOperator = counter++ > 0 ? " AND " : string.Empty;
            sb.Append($"{logicalOperator}HAKUNIMI LIKE '%{HAKUNIMISearchKey}%'");
        }
        if (GROUPSearchKey != string.Empty)
        {
            logicalOperator = counter++ > 0 ? " AND " : string.Empty;
            sb.Append($"{logicalOperator}KONSERNI LIKE '%{GROUPSearchKey}%'");
        }
        if (BUSINESSIDSearchKey != string.Empty)
        {
            logicalOperator = counter++ > 0 ? " AND " : string.Empty;
            sb.Append($"{logicalOperator}LY LIKE '%{BUSINESSIDSearchKey}%'");
        }

        this.MainDataTable.DefaultView.RowFilter = sb.ToString();
    }

最后一个解决方案是迄今为止最短的,所以我更喜欢它。
您只需将 OR 替换为 AND(我的错)。

public void EnableRowFiltering()
{
  this.MainDataTable.DefaultView.RowFilter = 
    $"YRNRO LIKE '{this.YRNROSearchKey}*'" + 
    $"AND HAKUNIMI LIKE '{this.HAKUNIMISearchKey}*'" +
    $"AND KONSERNI LIKE '{this.GROUPSearchKey}*'" +
    $"AND LY LIKE '{this.BUSINESSIDSearchKey}*'";
}

第一个解决方案的表达式字符串有一个尾随AND运算符,这会导致错误消息。 使用运算符为每个表达式(操作数)添加前缀将修复它。

请注意,必须删除表达式的前导%才能使其成为“开头为”表达式。 具有前导%和尾随% (通配符运算符)将表示“包含”。

因为和空字符串变量会产生类似"Column LIKE '%'的表达式,并且因为${null}返回"" (空字符串),您可以缩短代码:

public void EnableRowFiltering()
{
  StringBuilder sb = new StringBuilder();
  sb.Append($"YRNRO LIKE '{this.YRNROSearchKey}%'");
  sb.Append($"AND KONSERNI LIKE '{this.GROUPSearchKey}%'");
  sb.Append($"AND LY LIKE '{this.BUSINESSIDSearchKey}%'");

  this.MainDataTable.DefaultView.RowFilter = sb.ToString();
}

第二个解决方案的表达似乎是正确的,但不知何故分配变得混乱。 在定义过滤器表达式以修复它后分配过滤器表达式。

因为和空字符串变量会产生类似"Column LIKE '*'的表达式,并且因为${null}返回"" (空字符串),您可以缩短代码:

public void EnableRowFiltering()
{ 
  string YRNRO = $"YRNRO LIKE '{this.YRNROSearchKey}*'";
  string HAKUNIMI = $" AND HAKUNIMI LIKE '{this.HAKUNIMISearchKey}*'";
  string GROUP = $" AND KONSERNI LIKE '{this.GROUPSearchKey}*'";
  string BUSINESSID = $" AND LY LIKE '{this.BUSINESSIDSearchKey}*'";

  this.MainDataTable.DefaultView.RowFilter = YRNRO + HAKUNIMI + GROUP + BUSINESSID;
}

三个方案都经过修复和改进后,都简化为基本相同的方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM