C# 如何为 WPF ListView 禁用 XAML 中的某些项目
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1111233/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to disable some items in XAML for a WPF ListView
提问by KevinDeus
OK, sorry for the overly broad question, but let's see what you guys suggest....
好的,对于过于宽泛的问题感到抱歉,但让我们看看你们的建议......
I have a WPF ListView loaded by an XML file, using XAML (code below)
我有一个由 XML 文件加载的 WPF ListView,使用 XAML(下面的代码)
I have a second XML file with items that match what is in my ListView. However, if there is nota match in the 2nd file, then I want that ListItem disabled.
我有第二个 XML 文件,其中的项目与我的 ListView 中的项目相匹配。但是,如果第二个文件中没有匹配项,那么我希望禁用该 ListItem。
A simple example:
一个简单的例子:
My ListView has in it:
我的 ListView 中有:
Joe
Fred
Jim
(because it was loaded with the first XML file)
(因为它是用第一个 XML 文件加载的)
My second XML file has (essentially):
我的第二个 XML 文件有(基本上):
Joe
Jim
I want the ListView to somehow consume this second file as well, resulting in "Fred" being disabled.
我希望 ListView 也以某种方式使用第二个文件,从而导致“Fred”被禁用。
I am assuming that it would be some sort of "Filter" I would apply somewhere in XAML.
我假设这将是某种“过滤器”,我将在 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>
采纳答案by Charlie
This is a fairly complex task, so you should consider doing this mostly in code rather than in XAML. If you were to do this entirely in code-behind, you could add a handler for the ListView.Loaded event, and then do all the logic of adding items and disabling certain items there. Admittedly, the ListView would not be data-bound, but in a special case like this you might be better off without the binding.
这是一项相当复杂的任务,因此您应该考虑主要在代码中而不是在 XAML 中执行此操作。如果您要完全在代码隐藏中执行此操作,您可以为 ListView.Loaded 事件添加一个处理程序,然后在那里执行添加项目和禁用某些项目的所有逻辑。诚然,ListView 不会是数据绑定的,但在这样的特殊情况下,没有绑定可能会更好。
However, to show that this can be done in XAML, and using mark-up similar to yours, I have constructed the following example. My example uses Lists rather than XmlDataProvider, but the gist of it is exactly the same; you would just need to replace my code that builds Lists with your code that loads XML.
但是,为了表明这可以在 XAML 中完成,并使用类似于您的标记,我构建了以下示例。我的示例使用列表而不是 XmlDataProvider,但其要点完全相同;您只需要将我构建列表的代码替换为加载 XML 的代码。
Here is my code-behind file:
这是我的代码隐藏文件:
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;
}
}
This simply defines a couple lists, and the Personclass definition, which holds a Namestring.
这只是定义了几个列表和Person类定义,其中包含一个Name字符串。
Next, my XAML mark-up:
接下来,我的 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>
Here I bind the IsEnabled property of each ListViewItem to the Name property of the current Person. I then supply a Converter that will check to see if that Person's Name is on the List. The ConverterParameter points to the FilterList, which is the equivalent of your second XML file. Finally, here is the converter:
这里我将每个 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();
}
}
And the end result:
最终结果:
回答by Chen Kinnrot
My solution is not so simple, you need to create a dataTemplate for the items in the list. the data template should have a datatrigger, that means that you need to have some kind of property in the itemssource that tells you if the item exists in the other xml file.
我的解决方案没那么简单,你需要为列表中的项目创建一个dataTemplate。数据模板应该有一个数据触发器,这意味着您需要在 itemssource 中有某种属性来告诉您该项目是否存在于另一个 xml 文件中。
so what i'm trying to say is that u need to read the xml file from code and generate your own custom class that will contain the name prop and the Exists property and bind it to the other file,
所以我想说的是,您需要从代码中读取 xml 文件并生成您自己的自定义类,该类将包含 name prop 和 Exists 属性并将其绑定到另一个文件,
another solution that i thought of wile i was writing the answer is to bind the isenabled property of the item to a converter that will get the name and check the other file and return a boolean.
我在写答案时想到的另一个解决方案是将项目的 isenabled 属性绑定到一个转换器,该转换器将获取名称并检查另一个文件并返回一个布尔值。