如何在XAML中为WPF ListView禁用某些项目

时间:2009-07-10 18:33:23

标签: c# wpf xaml listview filter

好的,抱歉这个过于宽泛的问题,但让我们看看你们的建议....

我有一个XML文件加载的WPF ListView,使用XAML(下面的代码)

我有第二个XML文件,其中的项目与我的ListView中的项目相匹配。但是,如果第二个文件中有匹配,那么我希望禁用ListItem。

一个简单的例子:

我的ListView包含在其中:

                   Joe
                   Fred
                   Jim  

(因为它加载了第一个XML文件)

我的第二个XML文件(基本上):

                  Joe
                  Jim

我希望ListView以某种方式使用第二个文件,导致“Fred”被禁用。

我假设它会是某种“过滤器”我会在XAML的某处应用。

<ListView Name="lvwSourceFiles" 
          Margin="11,93,0,12" VerticalContentAlignment="Center" 
          HorizontalAlignment="Left" Width="306"
          Cursor="Hand" TabIndex="6" 
          ItemsSource="{Binding}"
          SelectionMode="Multiple"
          SelectionChanged="lvwSourceFiles_SelectionChanged" >
    <ListBox.DataContext>
        <XmlDataProvider x:Name="xmlSourceFiles" XPath="AssemblyUpdaterSource/sources/source/File" />
    </ListBox.DataContext>
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <EventSetter Event="PreviewMouseRightButtonDown"
                         Handler="OnSourceListViewItemPreviewMouseRightButtonDown" />
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

2 个答案:

答案 0 :(得分:10)

这是一项相当复杂的任务,因此您应该考虑在代码中而不是在XAML中执行此操作。如果您完全在代码隐藏中执行此操作,则可以为ListView.Loaded事件添加处理程序,然后执行添加项目和禁用某些项目的所有逻辑。不可否认,ListView不会受数据限制,但在这种特殊情况下,如果没有绑定,你可能会更好。

但是,为了表明这可以在XAML中完成,并使用类似于你的标记,我构建了以下示例。我的例子使用Lists而不是XmlDataProvider,但它的要点完全相同;您只需要使用加载XML的代码替换构建Lists的代码。

这是我的代码隐藏文件:

public partial class Window2 : Window
{
    private List<Person> _persons = new List<Person>();

    public Window2()
    {
        InitializeComponent();

        _persons.Add(new Person("Joe"));
        _persons.Add(new Person("Fred"));
        _persons.Add(new Person("Jim"));
    }

    public List<Person> Persons
    {
        get { return _persons; }
    }

    public static List<Person> FilterList
    {
        get
        {
            return new List<Person>()
            {
                new Person("Joe"), 
                new Person("Jim")
            };
        }
    }
}

public class Person
{
    string _name;

    public Person(string name)
    {
        _name = name;
    }

    public string Name
    {
        get { return _name; }
        set { _name = value; }
    }

    public override string ToString()
    {
        return _name;
    }
}   

这只是定义了几个列表,以及 Person 类定义,它包含 Name 字符串。

接下来,我的XAML标记:

<Window x:Class="TestWpfApplication.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestWpfApplication"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="Window2" Height="300" Width="300"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
    <local:PersonInListConverter x:Key="personInListConverter"/>
    <ObjectDataProvider x:Key="filterList" ObjectInstance="{x:Static local:Window2.FilterList}"/>
</Window.Resources>
<StackPanel>
    <ListView ItemsSource="{Binding Persons}"
              SelectionMode="Multiple"
              Name="lvwSourceFiles" Cursor="Hand" VerticalContentAlignment="Center">
        <ListView.ItemContainerStyle>
            <Style TargetType="{x:Type ListViewItem}">
                <Setter Property="IsEnabled" 
                        Value="{Binding Name, Converter={StaticResource personInListConverter}, ConverterParameter={StaticResource filterList}}"/>
            </Style>
        </ListView.ItemContainerStyle>
    </ListView>
</StackPanel>

这里我将每个ListViewItem的IsEnabled属性绑定到当前Person的Name属性。然后我提供了一个转换器,它将检查该人员名称是否在列表中。 ConverterParameter指向FilterList,它等同于您的第二个XML文件。最后,这是转换器:

public class PersonInListConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string name = (string)value;
        List<Person> persons = (parameter as ObjectDataProvider).ObjectInstance as List<Person>;

        return persons.Exists(person => name.Equals(person.Name));
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

最终结果:

alt text

答案 1 :(得分:3)

我的解决方案并非如此简单,您需要为列表中的项目创建一个dataTemplate。 数据模板应该有一个datatrigger,这意味着你需要在itemssource中拥有某种属性,告诉你该项是否存在于另一个xml文件中。

所以我想说的是你需要从代码中读取xml文件并生成你自己的自定义类,它将包含名称prop和Exists属性并将其绑定到另一个文件,

我想到的另一个解决方案是我写的答案是将项目的isenabled属性绑定到一个转换器,它将获取名称并检查另一个文件并返回一个布尔值。

相关问题