WPF binding where value = X
Hi Just wanna hear if its possible in xaml to bind to a list, where a value has a certain value. Ex. in the following example, is it possible with Xaml only to only show the items, where Price = 20?
I'm asking because I'm going to Bind a list of object containing another list, where I only wanna show certain item, depending on there values. Therefor I'm trying to avoid a C# solution.
MainWindow.xaml
<Window x:Class="Binding_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<ListView ItemsSource="{Binding}"/>
</Grid>
</Window>
MainWindow.xaml.cs
public MainWindow()
{
DataContext = BuildList();
InitializeComponent();
}
List<Product> BuildList()
{
var list = new List<Product>();开发者_JAVA技巧
var y = 1;
for (var i = 0; i < 100; i++)
{
list.Add(new Product{Name = string.Format("Item {0}",i), Price = y++ * 10 });
if (y > 3)
y = 1;
}
return list;
}
Product.cs
public class Product
{
public string Name { get; set; }
public int Price { get; set; }
public override string ToString()
{
return string.Format("{0} \t{1}", Name, Price.ToString("C2"));
}
}
Use a CollectionViewSource with an appropriate filter. In this case the xaml would look like this:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<CollectionViewSource Source="{Binding}" x:Key="filtered" Filter="CollectionViewSource_Filter" />
</Window.Resources>
<Grid>
<ListView ItemsSource="{Binding Source={StaticResource filtered}}"/>
</Grid>
and the filter event would look like this:
private void CollectionViewSource_Filter(object sender, FilterEventArgs e)
{
if ((e.Item as Product).Price == 20)
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
Use a ValueConverter
If you create a ValueConvert that takes filter value as a parameter you can then make it return only the entries you want.
public class FilterConverter : IValueConverter {
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) {
var list=value as List<Product>();
if (list==null) return Binding.DoNothing;
var stringPrice=parameter as string;
int price;
if (!int.TryParse(stringPrice,out price)) return Binding.DoNothing;
return list.Where(i=>i.Price==price).ToList();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) {
return Binding.DoNothing;
}
}
Then create a static resource for your converter and reference it in the binding
<Window x:Class="Binding_Test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:c="PUT A REFERENCE TO THE CONVERTER NAMESPACE HERE!!!"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<c:FilterConverter x:Key="filter" />
</Window.Resources>
<Grid>
<ListView ItemsSource="{Binding Converter={StaticResource filter},ConverterParameter=20}"/>
</Grid>
Stolen from here:
WPF has built-in support for filtering items in a list. ICollectionView has a Filter property, which can be set to an instance of Predicate — a delegate which takes a single Object argument and returns a bool. Each item in the list is passed through that filter to determine if it is filtered in or out.
An example how to use the filter property can be found here
Use a custom DataTemplate in your ListView and use a DataTrigger to determine which items should be shown or not. Something like:
<Style x:Key="HideUnlessSomeConditionIsTrue" TargetType="{x:Type TextBlock}">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding SomeProperty}" Value="SomeValue">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
</Style.Trigger>
</Style>
<TextBlock Style="{StaticResource HideUnlessSomeConditionIsTrue}" ... />
I support Leom Burke's solution.
An alternative solution (in your case) could be to use an ObjectDataProvider with MethodParameters.
Have a look at the examples section of this page:
http://msdn.microsoft.com/en-us/library/system.windows.data.objectdataprovider.methodname.aspx
精彩评论