好的,抱歉这个过于宽泛的问题,但让我们看看你们的建议....
我有一个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>
答案 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();
}
}
最终结果:
答案 1 :(得分:3)
我的解决方案并非如此简单,您需要为列表中的项目创建一个dataTemplate。 数据模板应该有一个datatrigger,这意味着你需要在itemssource中拥有某种属性,告诉你该项是否存在于另一个xml文件中。
所以我想说的是你需要从代码中读取xml文件并生成你自己的自定义类,它将包含名称prop和Exists属性并将其绑定到另一个文件,
我想到的另一个解决方案是我写的答案是将项目的isenabled属性绑定到一个转换器,它将获取名称并检查另一个文件并返回一个布尔值。