簡體   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