WPF MMV ICollectionView过滤许多属性

时间:2017-01-12 15:28:05

标签: c# wpf mvvm

我有一个问题,我使用datagrid和一些使用命令的文本框过滤系统创建,所以xaml部分看起来像:

System.Web.HttpException (0x80004005): DataBinding: 'System.Data.DataRow' does not contain a property with the name 'EmployeeID'. at System.Web.UI.DataBinder.GetPropertyValue(Object container, String propName) at System.Web.UI.DataBinder.Eval(Object container, String[] expressionParts) at System.Web.UI.DataBinder.Eval(Object container, String expression) at System.Web.UI.TemplateControl.Eval(String expression) at ASP.default_aspx.__DataBinding__control130(Object sender, EventArgs e) in c:\Users\SkillSet\Default.aspx:line 230 at System.Web.UI.Control.OnDataBinding(EventArgs e) at System.Web.UI.Control.DataBind(Boolean raiseOnDataBinding) at System.Web.UI.Control.DataBind() at System.Web.UI.Control.DataBindChildren() at System.Web.UI.Control.DataBind(Boolean raiseOnDataBinding) at System.Web.UI.Control.DataBind() at System.Web.UI.Control.DataBindChildren() at System.Web.UI.Control.DataBind(Boolean raiseOnDataBinding) at System.Web.UI.Control.DataBind() at System.Web.UI.WebControls.GridView.CreateRow(Int32 rowIndex, Int32 dataSourceIndex, DataControlRowType rowType, DataControlRowState rowState, Boolean dataBind, Object dataItem, DataControlField[] fields, TableRowCollection rows, PagedDataSource pagedDataSource) at System.Web.UI.WebControls.GridView.CreateChildControls(IEnumerable dataSource, Boolean dataBinding) at System.Web.UI.WebControls.CompositeDataBoundControl.PerformDataBinding(IEnumerable data) at System.Web.UI.WebControls.GridView.PerformDataBinding(IEnumerable data) at System.Web.UI.WebControls.DataBoundControl.OnDataSourceViewSelectCallback(IEnumerable data) at System.Web.UI.DataSourceView.Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback) at System.Web.UI.WebControls.DataBoundControl.PerformSelect() at System.Web.UI.WebControls.BaseDataBoundControl.DataBind() at System.Web.UI.WebControls.GridView.DataBind() at _Default.BindGrid() in c:\Users\SkillSet\Default.aspx.cs:line 366 

数据网格:                 

           <GroupBox Header="Filtry">
                <StackPanel Orientation="Horizontal" >
                    <Label Content="Imie" />
                    <TextBox x:Name="txtFirstnameFilter" MinWidth="50" Text="">
                        <i:Interaction.Behaviors>
                            <b:PropertyChangedCommandBehavior DependencyPropertyName="Text" PropertyChangedCommand="{Binding FirstameCommand}" />
                        </i:Interaction.Behaviors>
                    </TextBox>
                    <Label Content="Nazwisko" />
                    <TextBox x:Name="txtLastnameFilter" MinWidth="50" Text="">
                        <i:Interaction.Behaviors>
                            <b:PropertyChangedCommandBehavior DependencyPropertyName="Text" PropertyChangedCommand="{Binding LastnameCommand}" />
                        </i:Interaction.Behaviors>
                    </TextBox>
                </StackPanel>
            </GroupBox>

使用ICommand我设法创建看起来像

的简单过滤器
                <DataGrid.Columns>
                    <DataGridTextColumn Binding="{Binding firstname}" Header="Imię" />
                    <DataGridTextColumn Binding="{Binding lastname}" Header="Nazwisko" />
                    <DataGridTextColumn Binding="{Binding email}" Header="E-Mail" />
                </DataGrid.Columns>

他被命令召唤出来:

    public void Filter(object obj)
    {
        this.Candidates.Filter = item =>
        {
            Candidate candidate = item as Candidate;
            return candidate.firstname.Contains(obj.ToString()) || candidate.lastname.Contains(obj.ToString());
        };

        this.Candidates.Refresh();
    }

这就是问题所在。当我仅使用名称进行过滤时,它工作得很好,但是当我在filter方法中调用LastnameCommand Im时出现空引用异常时,当我输入名称时,姓氏应该是空的。

现在有一种方法来聚合过滤器,所以它会排序,例如,如果我把名字输入它将过滤所有名称,如果我输入姓氏,它将过滤所有名称和姓氏?

1 个答案:

答案 0 :(得分:1)

您应该确保Filter方法不会抛出任何异常:

public void Filter(object obj)
{
    if (obj == null)
        return;

    this.Candidates.Filter = item =>
    {
        Candidate candidate = item as Candidate;
        if (candidate == null)
            return false;

        string name = obj.ToString();

        return (!string.IsNullOrEmpty(candidate.firstname) && candidate.firstname.Contains(name))
            || (!string.IsNullOrEmpty(candidate.lastname) && candidate.lastname.Contains(name));
    };
    this.Candidates.Refresh();
}

但是如果你想同时过滤名字和姓氏,你应该将TextBoxes绑定到视图模型的两个源属性,并在这些的setter中调用Filter方法:

<TextBox x:Name="txtFirstnameFilter" MinWidth="50" Text="{Binding FirstNameToFilterOn}" />
<Label Content="Nazwisko" />
<TextBox x:Name="txtLastnameFilter" MinWidth="50" Text="{Binding LastNameToFilterOn}" />
private string _f;
public string FirstNameToFilterOn
{
    get { return _f; }
    set { _f = value; Filter(); }
}

private string _l;
public string LastNameToFilterOn
{
    get { return _l; }
    set { _l = value; Filter(); }
}

public void Filter()
{
    this.Candidates.Filter = item =>
    {
        Candidate candidate = item as Candidate;
        if (candidate == null)
            return false;

        return (string.IsNullOrEmpty(FirstNameToFilterOn) || string.IsNullOrEmpty(candidate.firstname) || candidate.firstname.Contains(FirstNameToFilterOn))
         && (string.IsNullOrEmpty(LastNameToFilterOn) || string.IsNullOrEmpty(candidate.lastname) || candidate.lastname.Contains(LastNameToFilterOn));
    };
    this.Candidates.Refresh();
}

否则,Filter方法对其他名称一无所知,即它只知道您作为参数传递给该命令的名称(名字或姓氏)。