Dies ist eine ziemlich komplexe Aufgabe, daher sollten Sie in Betracht ziehen, dies hauptsächlich im Code und nicht in XAML zu tun. Wenn Sie dies vollständig in Code-Behind tun würden, könnten Sie einen Handler für das ListView.Loaded-Ereignis hinzufügen und dann die gesamte Logik des Hinzufügens von Elementen und des Deaktivierens bestimmter Elemente dort ausführen. Zugegeben, die ListView wäre nicht datengebunden, aber in einem speziellen Fall wie diesem wäre es vielleicht besser, ohne die Bindung.
Um jedoch zu zeigen, dass dies in XAML gemacht werden kann, und mit Mark-up ähnlich wie Ihres, habe ich das folgende Beispiel konstruiert. In meinem Beispiel werden Listen und nicht XmlDataProvider verwendet, aber der Kern davon ist genau derselbe; Sie müssten nur meinen Code, der Listen erstellt, durch Ihren Code ersetzen, der XML lädt.
Hier ist meine Code-Behind-Datei:
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;
}
}
Dies einfach definiert ein paar Listen und die Person Klassendefinition, die einen Namen Zeichenfolge enthält.
Als nächstes mein XAML mark-up:
<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>
Hier binde ich die IsEnabled Eigenschaft jeden ListViewItem auf die Eigenschaft Namen der aktuellen Person. Ich stelle dann einen Konverter zur Verfügung, der prüft, ob der Name dieser Person auf der Liste ist. Der ConverterParameter verweist auf die FilterList, die Ihrer zweiten XML-Datei entspricht. Schließlich, hier ist der Konverter:
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();
}
}
Und das Endergebnis:
@Chen könnten Sie ein Beispiel geben, wie so zu einem Konverter zu binden? – KevinDeus
Nicht unbedingt. Sie müssen hierfür kein DataTemplate verwenden. Die Bindung mit Konverter kann im ItemContainerStyle erfolgen. – Charlie