难以为自定义自动筛选组合框定义筛选谓词
本文关键字:筛选 组合 定义 谓词 自定义 | 更新日期: 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的帮助。