我有一个绑定到CollectionViewSource的ListView。我跟随这篇文章(被许多人引用)进行多重过滤:http://www.zagstudio.com/blog/456#.UG8r6E1lWLE
我为测试设置了两个复选框,它们只添加了一个过滤器。每当我首先点击其中一个时,过滤器就会添加到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;
}
}
就像我说的,第一个过滤器总是有效的。第二个总是使屏幕空白。有什么想法吗?
您正在为两个过滤器重新使用过滤器字符串,一旦选中每个复选框,将应用两个过滤器。所以如果你:
- 选中复选框1,则filterString将为"Standard",并将连接shippingMethodFilter
- 选中复选框2,则filterString将为"TX",billingStateFilter将挂起
在任何时候都不会解除shippingMethodFilter的挂钩。因此,它将继续基于filterString"TX"进行过滤。
您可能应该添加一个过滤器方法,检查checkBox1/checkBox2是否被选中,然后可选地应用它的过滤逻辑。类似于:
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;
}
我已经发布了一个关于这方面的博客:https://hoomanvisualstudio.blogspot.com/b/post-preview?token=mpPyAk0BAAA.ygnewdzslszANX8AchX0hg.uW17QZR22-f_JUqjDTBcyA&postId=42004491240358821673&type=POST
有很多方法。一个简单的方法是将条件滚动到一个谓词中。
MyViewModel MyViewModel=新的MyViewModel();
//将使用您的筛选器的集合var _itemSourceList=myViewModel.MyCollection;
var filter=新谓词(item=>((Model)item).FirstName.ToString().Contains("John")&;((模型)项).LastName.ToString().Contains("Doe"));
_itemSourceList.Filter=筛选器;myDataGrid.ItemsSource=myViewModel.MyCollection;
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;
}
}
这是我正在创建的一个过滤器的代码。它适用于第一个过滤器,因为所有与过滤器不匹配的订单都不被接受。但当我检查第二个过滤框时,没有一个订单显示出来,因为最初接受的订单中有一个是真的,现在它们也不被接受,没有留下任何订单