【问题标题】:How to disable some items in XAML for a WPF ListView如何为 WPF ListView 禁用 XAML 中的某些项目
【发布时间】:2010-11-09 19:41:36
【问题描述】:

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

我有一个由 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>

【问题讨论】:

    标签: c# wpf xaml listview filter


    【解决方案1】:

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

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

    这是我的代码隐藏文件:

    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();
        }
    }
    

    最终结果:

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

      • @Chen 你能举例说明如何绑定到这样的转换器吗?
      • 不一定。您不需要为此使用 DataTemplate。与转换器的绑定可以在 ItemContainerStyle 中完成。
      猜你喜欢
      • 2011-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-15
      • 1970-01-01
      • 2015-09-08
      • 2011-05-08
      相关资源
      最近更新 更多