难以为自定义自动筛选组合框定义筛选谓词

本文关键字:筛选 组合 定义 谓词 自定义 | 更新日期: 2023-09-27 18:10:19

在尝试使用自动过滤的组合框(在WPF中自动过滤组合框)时,新的组合框控件接受IEnumerable集合源:

protected override void OnItemsSourceChanged(System.Collections.IEnumerable oldValue, System.Collections.IEnumerable newValue)
{
     if (newValue != null)
     {
          ICollectionView view = CollectionViewSource.GetDefaultView(newValue);
          view.Filter += this.FilterPredicate;
     }
     if (oldValue != null)
     {
           ICollectionView view = CollectionViewSource.GetDefaultView(oldValue);
           view.Filter -= this.FilterPredicate;
     }
     base.OnItemsSourceChanged(oldValue, newValue);
}

IEnumerable newValue在视图模型中定义为:

public ObservableCollection<View_Small_Company> Companies

并绑定到xaml中的控件,如:

<wc:AutoFilteredComboBox  ItemsSource="{Binding PrimaryInsurance.Companies}"
                          ItemTemplate="{StaticResource CompanyTemplate}"
                          IsEditable="True"
                          IsTextSearchEnabled="True" 
                          TextSearch.TextPath="Companyname"
                          IsTextSearchCaseSensitive="False"               
                          Height="20" 
                          HorizontalAlignment="Left" 
                          Margin="162,235,0,0" 
                          VerticalAlignment="Top" 
                          Width="411"  />

我的问题是在谓词:

 private bool FilterPredicate(object value)
            {
                // We don't like nulls.
                if (value == null)
                    return false;
                // If there is no text, there's no reason to filter.
                if (this.Text.Length == 0)
                    return true;
                string prefix = this.Text;
                // If the end of the text is selected, do not mind it.
                if (this.length > 0 && this.start + this.length == this.Text.Length)
                {
                    prefix = prefix.Substring(0, this.start);
                }

                // The "value" is the Item being displayed. The Item being displayed can be styled in the xaml.
                // Example:
                //    ItemTemplate="{StaticResource CompanyTemplate}" uses the type Stargate_V.DataService.View_Small_Company 
                // so
                //    the "value.ToString() would give:  "Stargate_V.DataService.View_Small_Company" making StartsWith() useless.
                // value.ToString() will only work with string items.

                return value.ToString()
                    .StartsWith(prefix, !this.IsCaseSensitive, CultureInfo.CurrentCulture);
            }

如上所述,"value"返回的是自定义类——而不是字符串——因此谓词失败。此控件位于单独的自定义库中,与正在筛选的自定义类无关。

那么获得值的自定义类以便我可以对值进行过滤的最佳方法是什么?公司名称?

还是我走远了,有更好的方法?

难以为自定义自动筛选组合框定义筛选谓词

我认为这里有一些可以改进的地方。首先,你没有考虑在字符串中间有一个选择的情况。即。'ABCDE'是字符串,但'CD'被选中。不过,您仍然可以简单地检查选择长度,如果它大于零,则执行从0到选择start的子字符串。

接下来,更重要的是,除非您为组合框使用数据路径,否则您不应该将过滤器放在组合框本身中,原因正是您提到的:项目可以在其他地方被模板化,这意味着显示的内容由模板决定。那就是你不能在那里使用ToString的原因。相反,正确的做法是将谓词传递给控件,而不是试图让控件处理谓词本身(正如您指出的那样,由于数据模板,无法确定谓词)。这样,作为模板作者的您就知道要显示什么,并可以相应地编写谓词。

TLDR版本:

控件的使用者应该将谓词传递给控件,因为控件。

希望你明白。

这看起来像是一个hack,我更喜欢@MarguilV的建议(这不是最好的答案)。然而,这似乎是一个简单的解决方案:重写ToString()属性为:

public partial class View_Small_Company
{
    public override string ToString()
    {
        return Companyname;
    }
} 

现在控件中的谓词将正常工作:)

注意:一个更好的方法是在我的下一个问题中如何将函数绑定到依赖属性。我感谢汤姆。感谢Maruska的帮助。