3

CollectionViewSource にバインドされた ListView があります。複数のフィルタリングについては、この記事 (多くの人が参照) に従いました: http://www.zagstudio.com/blog/456#.UG8r6E1lWLE

フィルターを追加するだけのテスト用に 2 つのチェックボックスを設定しました。最初にどちらかをクリックすると、フィルターが CollectionViewSource に追加され、機能します。次に、反対のチェックボックスをクリックすると、他のフィルターが CollectionViewSource に追加され、両方のフィルターが機能する代わりに、リストビューが空白になります (データに基づいてはならない場合、これはチェックボックスをチェックする順序で発生します)

関連するコードは次のとおりです: (背景: このアプリケーションは、ソフトウェアを出荷するための「注文」のフィルタリングを処理します)

注文の読み込み:

public class Order
{
    public int index { get; set; }
    public string host { get; set; }
    public Int64 orderNumber { get; set; }
    public string batchStatus { get; set; }
    public string sku { get; set; }
    public int numItems { get; set; }
    public string orderSource { get; set; }
    public string sourceOrderNumber { get; set; }
    public DateTime orderDate { get; set; }
    public DateTime orderTime { get; set; }
    public int customerID { get; set; }
    public string shipMethod { get; set; }
    public string billingState { get; set; }
    public bool statusChanged { get; set; }
    public int numSkus { get; set; }
    public string marketName { get; set; }
    public float weight { get; set; }
}

public class Orders : ObservableCollection<Order>
{
    public Orders()
    {
        SqlDataReader reader1 = cmd.ExecuteReader();
        while (reader1.Read())
        {
            Order order = new Order();

            order.host = (string)safeGetString(reader1, 0);
            order.orderNumber = (Int64)reader1["OrderNumber"];
            order.batchStatus = (string)safeGetString(reader1, 2);
            order.orderSource = (string)safeGetString(reader1, 3);
            order.sourceOrderNumber = safeGetString(reader1, 4);
            order.orderDate = (DateTime)reader1["OrderDate"];
            order.customerID = (int)reader1["CustomerID"];
            order.shipMethod = (string)safeGetString(reader1, 7);
            order.billingState = (string)safeGetString(reader1, 8);
            order.numItems = (int)reader1["NumItems"];
            order.numSkus = (int)reader1["NumSKUs"];
            order.marketName = (string)safeGetString(reader1, 11);
            order.weight = (float)(double)reader1["ShippedWeight"];


            this.Add(order);
        }
        reader1.Close();
    }

CollectionViewSource の設定:

cvs = (CollectionViewSource)(this.Resources["cvs"]);

チェックボックス関数: (テスト用に filterString を使用して「何をフィルタリングするか」をハードコーディング)

public void checkBox2_Checked(object sender, RoutedEventArgs e)
    {
        filterString = "TX";
        cvs.Filter += new FilterEventHandler(billingStateFilter);
    }
    public void checkBox1_Checked(object sender, RoutedEventArgs e)
    {
        filterString = "Standard";
        cvs.Filter += new FilterEventHandler(shippingMethodFilter);
    }

そして最後に、フィルター:

private void shippingMethodFilter(object sender, FilterEventArgs e)
    {
        Order order = e.Item as Order;
        if ((order.shipMethod != filterString))
        {
            e.Accepted = false;
        }
    }

    public void billingStateFilter(object sender, FilterEventArgs e)
    {
        Order order = e.Item as Order;
        if ((order.billingState != filterString))
        {
            e.Accepted = false;
        }
    }

私が言ったように、最初のフィルターは常に機能します。2 番目は常に画面を空白にします。何か案は?

4

3 に答える 3

1

両方のフィルターにフィルター文字列を再利用しています。各チェックボックスをオンにすると、両方のフィルターが適用されます。したがって、次の場合:

  1. checkBox1をチェックすると、filterStringが「標準」になり、shippingMethodFilterが接続されます。
  2. checkBox2をチェックすると、filterStringが「TX」になり、billingStateFilterが接続されます。

どの時点でもshippingMethodFilterがフック解除されていません。したがって、「TX」のfilterStringに基づいてフィルタリングを続行します。

おそらく、checkBox1 / checkBox2がチェックされているかどうかを確認するフィルターメソッドを1つ追加し、オプションでそのフィルターロジックを適用する必要があります。何かのようなもの:

private string shippingFilterString = "Shipping";
private string billingFilterString = "TX";

private void collFilter(object sender, FilterEventArgs e)
{
    Order order = e.Item as Order;
    if (checkBox1.IsChecked == true && (order.shipMethod != shippingFilterString ))
        e.Accepted = false;
    if (checkBox2.IsChecked == true && (order.billingState != billingFilterString ))
        e.Accepted = false;
}
于 2012-10-05T19:19:26.287 に答える
1

私はこれについてブログを投稿しました:

非常に多くの方法があります。簡単な方法の 1 つは、条件を 1 つの述語にまとめることです。

MyViewModel myViewModel = new MyViewModel();

// Filter を受け取るコレクション var _itemSourceList = myViewModel.MyCollection;

var filter = new Predicate(item => ((Model)item).FirstName.ToString().Contains("John") && ((Model)item).LastName.ToString().Contains("Doe"));

_itemSourceList.Filter = フィルター; myDataGrid.ItemsSource = myViewModel.MyCollection;

于 2015-04-28T18:16:05.243 に答える
0
for (i = 0; i < numberItemsFilterStrings.Length; i++)
            {
                switch (numberItemsFilterStrings[i])
                {
                    case "One Item":
                        if (order.numItems != 1)
                        {
                            e.Accepted = false;
                        }
                        break;
                    case "Between 2 - 5":
                        if ((order.numItems < 2) || (order.numItems > 5))
                        {
                            e.Accepted = false;
                        }
                        break;
                    case "Between 6 - 25":
                        if ((order.numItems < 6) || (order.numItems > 24))
                        {
                            e.Accepted = false;
                        }
                        break;
                    case "Greater Than 25":
                        if (order.numItems < 25)
                        {
                            e.Accepted = false;
                        }
                        break;
                }
            }

これは、私が作成しているフィルターの 1 つのコードです。フィルターに一致しない注文はすべて受け入れられないため、最初のフィルターで機能します。しかし、2 番目のフィルター ボックスをチェックすると、注文が表示されません。

于 2012-10-08T17:45:22.803 に答える