我有一个ListView,其ItemsSource设置为我的ViewModel的集合属性。 ViewModel上还有一个属性,比如'CurrentIndex',它随着代码的运行而变化。由于这种变化,我只想要ListViewItem,其ListView中与“CurrentIndex”匹配的索引会发生变化,比如说它的背景会改变颜色。当'CurrentIndex'更改时,我希望先前引用的ListViewItem被“重置”,即其背景更改为先前的颜色。有谁知道我怎么做到这一点?
我想过利用ListView的SelectedIndex属性,但这不起作用,因为用户可以单击ListView并更改选择,从而更改错误项目的背景。
ListViewItems通过XAML中的ItemTemplate进行模板化。
希望这是有道理的。
非常感谢您的任何帮助。
答案 0 :(得分:3)
这是另一种方法。您从a behavior that applies to WPF container controls like Grid
, StackPanel
, etc., and gives each of the children an attached ChildIndex
property开始。然后在ItemContainerStyle
的{{1}}中添加ListBox
,其使用DataTrigger
和多值转换器来比较每个MultiBinding
的{{1}} ListBoxItem
1}}到viewmodel上的ChildIndex
属性。
将行为应用于HighlightIndex
本身会更方便(实际上,您希望将其应用于ListBox
的祖先类ListBox
),但实际上,您可以在不在列表框中的内容上使用它。
XAML:
ItemsControl
行为:
<ListBox
ItemsSource="{Binding Items}"
>
<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
hbo:PanelBehaviors.IsChildPositionIndicated="True"
Orientation="Vertical"
/>
</ItemsPanelTemplate>
</ListBox.ItemsPanel>
<ListBox.ItemContainerStyle>
<Style
TargetType="ListBoxItem"
BasedOn="{StaticResource {x:Type ListBoxItem}}"
>
<Style.Triggers>
<DataTrigger Value="True">
<DataTrigger.Binding>
<MultiBinding
Converter="{StaticResource EqualsConverter}">
<Binding
Path="DataContext.HighlightIndex"
RelativeSource="{RelativeSource AncestorType=ListBox}"
/>
<Binding
Path="(hbo:PanelBehaviors.ChildIndex)"
RelativeSource="{RelativeSource Self}"
/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Background" Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
转换器:
using System.Windows;
using System.Windows.Controls;
namespace HollowEarth.Behaviors
{
public static class PanelBehaviors
{
public static void UpdateChildIndexProperties(Panel panel)
{
for (int i = 0; i < panel.Children.Count; ++i)
{
var child = panel.Children[i];
SetChildIndex(child, i);
}
}
#region PanelBehaviors.IsChildPositionIndicated Attached Property
public static bool GetIsChildPositionIndicated(Panel panel)
{
return (bool)panel.GetValue(IsChildPositionIndicatedProperty);
}
public static void SetIsChildPositionIndicated(Panel panel, bool value)
{
panel.SetValue(IsChildPositionIndicatedProperty, value);
}
/// <summary>
/// Behavior which causes the Panel to identify its first and last children with attached properties.
/// </summary>
public static readonly DependencyProperty IsChildPositionIndicatedProperty =
DependencyProperty.RegisterAttached("IsChildPositionIndicated", typeof(bool), typeof(PanelBehaviors),
new FrameworkPropertyMetadata(false, FrameworkPropertyMetadataOptions.AffectsArrange, IsChildPositionIndicated_PropertyChanged));
private static void IsChildPositionIndicated_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
Panel panel = (Panel)d;
((Panel)d).LayoutUpdated += (s, e2) => UpdateChildIndexProperties(panel);
}
#endregion PanelBehaviors.IsChildPositionIndicated Attached Property
#region PanelBehaviors.ChildIndex Attached Property
public static int GetChildIndex(UIElement obj)
{
return (int)obj.GetValue(ChildIndexProperty);
}
public static void SetChildIndex(UIElement obj, int value)
{
obj.SetValue(ChildIndexProperty, value);
}
public static readonly DependencyProperty ChildIndexProperty =
DependencyProperty.RegisterAttached("ChildIndex", typeof(int), typeof(PanelBehaviors),
new FrameworkPropertyMetadata(-1,
FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsParentArrange));
#endregion PanelBehaviors.ChildIndex Attached Property
}
}
viewmodel只是一个快捷方式:public class EqualsConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return Object.Equals(values[0], values[1]);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
,ObservableCollection<String> Items
,int HighlightIndex { get; set; }
。
答案 1 :(得分:1)
第二个解决方案:
如果你有一个绑定到ListView itemsSource的Item数组,并且每个Item都实现了INotifyPropertyChanged,那么你可以这样做:
<ListView ItemsSource="{Binding MyItemsList}">
<ListView.ItemTemplate>
<ItemContainerTemplate>
<Grid>
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Background" Value="Transparent"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ShouldChangeBackground}" Value="true">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
</ItemContainerTemplate>
</ListView.ItemTemplate>
</ListView>
ShouldChangeBackground是Item内的布尔值。当你希望它改变背景颜色时,你将这个布尔值设置为true,然后将它设置为False,它应该恢复正常。
另一种解决方案可能是使用转换器:
class TrueToBackgroundConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is Boolean && (Boolean)value)
return Brushes.Red;
return Brushes.Transparent;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
并在您的代码中:
<ListView ItemsSource="{Binding Element, FallbackValue=123123213213123213213}">
<ListView.ItemTemplate>
<ItemContainerTemplate>
<Grid Background="{Binding ShouldChangeBackground, Converter={StaticResource TrueToBackgroundConverter}}">
</Grid>
</ItemContainerTemplate>
</ListView.ItemTemplate>
</ListView>