WPF MVVM:按列表视图

时间:2017-08-01 07:16:30

标签: c# wpf listview mvvm collectionview

我在listview中有gridview。有一栏,"部门"这是绑定到一个财产"部门"在模型中它也与一个对流器相关联。

Converter获取来自属性的值,并以另一种形式显示它(使用另一个字符串)。

例如,如果此属性"部门"的值为" 100AB"在列中显示为"财务",如果值到达" 200CB"在列中显示"管理"等等...

我的问题是使用过滤器过滤listview时。在内部,它按" 100AB"," 200CB"而不是显示的值"财务"和"管理",那么如何解决这个问题?

查看(xaml)

<ListView Grid.Row="1" Grid.Column="0"
          Name="MyListView" 
          ItemsSource="{Binding Path=View}" 

<GridViewColumn Header="Department" Width="190"
                DisplayMemberBinding="{Binding Department, Converter={StaticResource DeptTypeConverter}}">
    <GridViewColumn.CellTemplate>
        <DataTemplate>
             <TextBlock TextAlignment="Right"/>
        </DataTemplate>
    </GridViewColumn.CellTemplate>
</GridViewColumn>

转换器

public class DeptTypeConverter: IValueConverter
{
    #region Constants

    private const string DeptFinancialType = "100AB";
    private const string DeptAdminType = "200CB";

    private const string DeptFinancialView = "Finanacial";
    private const string DeptAdminView = "Administration";

    #endregion

    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // Do the conversion from drink type to present it in the view
        string s = (string)value;
        if (s == DeptFinancialType )
            return DeptFinancialView;
        else if (s == DeptAdminType)
            return DeptAdminView;
        else
            throw new Exception(string.Format("Cannot convert, unknown value {0}", value));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        // Do the conversion from presentation to data type
        string s = (string)value;
        if (s.Equals(DeptFinancialView, StringComparison.InvariantCultureIgnoreCase))
            return DeptFinancialType;
        else if (s.Equals(DeptAdminView, StringComparison.InvariantCultureIgnoreCase))
            return DeptAdminType;
        else
            throw new Exception(string.Format("Cannot convert, unknown value {0}", value));
    }
}

在视图模型中过滤

private CollectionView view;

public CollectionView View
{
    get
    {
        return this.view;
    }

    private set
    {
        if (this.view == value)
        {
            return;
        }

        this.view = value;
        OnPropertyChanged("View");
    }
}

// This code in constructor
this.View = (CollectionView)CollectionViewSource.GetDefaultView(this.MyListView);
this.View.Filter = UserFilter;
//

private bool MyFilter(object item)
{
    if (String.IsNullOrEmpty(this.TextToFilter))
    {
        return true;
    }
    else
    {
        DataModel m = (item as DataModel);
        bool result = (m.Department.IndexOf(this.TextToFilter, StringComparison.OrdinalIgnoreCase) >= 0);

        return result;
    }
}

我在过滤器中有其他字段,我过滤了但是为了简单起见,我没有在MyFilter方法中指定。这个字段没有使用转换器,在这种情况下没有必要,只有在我提供的情况下才需要。

DataModel是数据模型,包含&#34; Department&#34;视图被绑定的属性。

this.TextToFilter是视图中的文本框,用于过滤。

ATTEMPT#1

我没有在DeptTypeConverter中使用ConvertBack,而是使用了Convert(无需在Convert方法中修改任何内容)。以下工作正常。

private bool MyFilter(object item)
{
    if (String.IsNullOrEmpty(this.TextToFilter))
    {
        return true;
    }
    else
    {
        DataModel m = (item as DataModel);

        bool result = (new Converters.DeptTypeConverter().Convert(m.Department, null, null, null).ToString().IndexOf(this.TextToFilter, StringComparison.OrdinalIgnoreCase) >= 0);

        return result;
    }
}

m.Department包含内部存储的值(不是显示的值)。

我认为最好使用Convert而不是ConvertBack作为用户在搜索时键入显示的文本(没有内部存储的值)。使用ConvertBack需要更多的逻辑来实现,并不像使用简单转换那么容易。

如果有人有更好的想法,请分享。任何想法或改进总是受欢迎的。我希望尽可能不打破MVVM模式架构。

1 个答案:

答案 0 :(得分:0)

我觉得最好的办法就是不要使用IValueConverter。我会更改您的DataModel类以添加新的DepartmentDisplay属性。对于GridViewColumn绑定和过滤使用DepartmentDisplay属性,对于在显示网格后对数据执行的操作,使用Department。这将是最简单和最MVVM的解决方案,它完全删除了IValueConverter。

的DataModel ....

public string Department { get; set; }

public string DepartmentDisplay
{
    get
    {
        if (Department == "100AB")
            return "Financial";
        if (Department == "200CB")
            return "Administration";

        return "";
    }
}

查看...

<GridViewColumn Header="Department" Width="190"
            DisplayMemberBinding="{Binding DepartmentDisplay}">

...视图模型

private bool MyFilter(object item)
{
    if (String.IsNullOrEmpty(this.TextToFilter))
    {
        return true;
    }
    else
    {
        DataModel m = (item as DataModel);
        bool result = (m.DepartmentDisplay.IndexOf(this.TextToFilter, StringComparison.OrdinalIgnoreCase) >= 0);

        return result;
    }
}