我正在尝试根据类的属性突出显示ListView中的一行。 ItemSource设置为ObservableCollection<FileInformation>
我需要确定该行是否应突出显示的属性包含在FileInformation
类 - bool IsPlaying
中。
这是我的ListView xaml:
<ListView Name="lvListView" Margin="0,0,0,35" AllowDrop="True" ItemsSource="{Binding FilesCollection}">
<ia:Interaction.Triggers>
<ia:EventTrigger EventName="Drop">
<cmd:EventToCommand Command="{Binding ListViewFileDrop}" PassEventArgsToCommand="True"/>
</ia:EventTrigger>
<ia:EventTrigger EventName="MouseDoubleClick">
<cmd:EventToCommand Command="{Binding ListViewDoubleClickCommand}" PassEventArgsToCommand="True"/>
</ia:EventTrigger>
</ia:Interaction.Triggers>
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Remove" Command="{Binding RemoveCommand}" CommandParameter="{x:Reference Name=lvListView}"/>
<MenuItem Header="Add File" Command="{Binding BrowseCommand}"/>
<MenuItem Header="Clear All" Command="{Binding ClearAllCommand}"/>
</ContextMenu>
</ListView.ContextMenu>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding RelativeSource={RelativeSource Self}, Path=IsPlaying, Converter={converters:TestConverter}}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Title" Width="350" DisplayMemberBinding="{Binding Title}"/>
<GridViewColumn Header="Time" Width="114"
DisplayMemberBinding="{Binding Time, Converter={converters:TimeSpanFormatConverter}}"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
这是我正在努力的部分:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="IsSelected" Value="{Binding RelativeSource={RelativeSource Self}, Path=IsPlaying, Converter={converters:TestConverter}}"/>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
现在为了突出显示我需要点击它的行,我希望仅当属性IsPlaying
设置为true时才以黄色突出显示。
这是财产声明:
public static readonly DependencyProperty IsPlayingProperty =
DependencyProperty.Register(nameof(IsPlaying), typeof(bool), typeof(FileInformation),
new PropertyMetadata(null));
private bool _isPlaying = false;
public bool IsPlaying
{
get => (bool)GetValue(IsPlayingProperty);
set
{
SetValue(IsPlayingProperty, value);
OnPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
答案 0 :(得分:0)
看看这是否有帮助。看一下转换器XAML(在绑定和Window.Resources中)。
我添加了一个只读数据网格来查看原始数据和一个用于切换(true / false)特定FileInformation.IsPlaying的按钮。
MainWindow.xaml
<Window x:Class="WpfApp13.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApp13"
xmlns:converters="clr-namespace:WpfApp13"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="525">
<Window.Resources>
<converters:TestConverter x:Key="TestConverter" />
<converters:TimeSpanFormatConverter x:Key="TimeSpanFormatConverter" />
</Window.Resources>
<Window.DataContext>
<local:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Since it looks like you want to play audio, I set SelectionMode to Single. Probably don't want to play multiple at once -->
<ListView Name="lvListView" Margin="0,0,0,35" AllowDrop="True" ItemsSource="{Binding FilesCollection}" SelectionMode="Single">
<!--<ia:Interaction.Triggers>
<ia:EventTrigger EventName="Drop">
<cmd:EventToCommand Command="{Binding ListViewFileDrop}" PassEventArgsToCommand="True"/>
</ia:EventTrigger>
<ia:EventTrigger EventName="MouseDoubleClick">
<cmd:EventToCommand Command="{Binding ListViewDoubleClickCommand}" PassEventArgsToCommand="True"/>
</ia:EventTrigger>
</ia:Interaction.Triggers>-->
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Remove" Command="{Binding RemoveCommand}" CommandParameter="{x:Reference Name=lvListView}"/>
<MenuItem Header="Add File" Command="{Binding BrowseCommand}"/>
<MenuItem Header="Clear All" Command="{Binding ClearAllCommand}"/>
</ContextMenu>
</ListView.ContextMenu>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="Beige"/>
<!-- The converter, TestConverter, isn't even needed but I'll leave it since you might be doing something else with it -->
<Setter Property="IsSelected" Value="{Binding Path=IsPlaying, Converter={StaticResource TestConverter}}"/>
<Style.Triggers>
<!--<Trigger Property="IsSelected" Value="True">-->
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" Value="Yellow"/>
</Trigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Title" Width="350" DisplayMemberBinding="{Binding Title}"/>
<GridViewColumn Header="Time" Width="114"
DisplayMemberBinding="{Binding Time, Converter={StaticResource TimeSpanFormatConverter}}"/>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
<DataGrid Grid.Row="1" AutoGenerateColumns="False" ItemsSource="{Binding FilesCollection}" IsReadOnly="True">
<DataGrid.Columns>
<DataGridCheckBoxColumn Binding="{Binding IsPlaying}" Header="IsPlaying" />
<DataGridTextColumn Binding="{Binding Title}" Header="Title" />
<DataGridTextColumn Binding="{Binding Time}" Header="Time" />
</DataGrid.Columns>
</DataGrid>
<Button Content="Toggle File 5 IsPlaying" Grid.Row="2" Margin="10" Click="Button_Click" />
</Grid>
</Window>
MainWindow.xaml.cs
using System;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace WpfApp13
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
((MainWindowViewModel)DataContext).PlayToggle(4); // I'm too lazy to use an ICommand...
}
}
public class MainWindowViewModel : DependencyObject
{
public ObservableCollection<FileInformation> FilesCollection
{
get { return (ObservableCollection<FileInformation>)GetValue(FilesCollectionProperty); }
set { SetValue(FilesCollectionProperty, value); }
}
public static readonly DependencyProperty FilesCollectionProperty = DependencyProperty.Register("FilesCollection", typeof(ObservableCollection<FileInformation>), typeof(MainWindowViewModel), new PropertyMetadata(null));
public MainWindowViewModel()
{
FilesCollection = new ObservableCollection<FileInformation>() {
new FileInformation() { Title = "File 1", IsPlaying = false, Time = new TimeSpan(0, 5, 1) },
new FileInformation() { Title = "File 2", IsPlaying = false, Time = new TimeSpan(0, 5, 2) },
new FileInformation() { Title = "File 3", IsPlaying = false, Time = new TimeSpan(0, 5, 3) },
new FileInformation() { Title = "File 4", IsPlaying = false, Time = new TimeSpan(0, 5, 4) },
new FileInformation() { Title = "File 5", IsPlaying = false, Time = new TimeSpan(0, 5, 5) },
new FileInformation() { Title = "File 6", IsPlaying = false, Time = new TimeSpan(0, 5, 6) },
new FileInformation() { Title = "File 7", IsPlaying = false, Time = new TimeSpan(0, 5, 7) },
new FileInformation() { Title = "File 8", IsPlaying = false, Time = new TimeSpan(0, 5, 8) },
new FileInformation() { Title = "File 9", IsPlaying = false, Time = new TimeSpan(0, 5, 9) },
};
}
public void PlayToggle(int idx)
{
FilesCollection[idx].IsPlaying = !FilesCollection[idx].IsPlaying;
}
}
public class FileInformation : DependencyObject
{
public static readonly DependencyProperty IsPlayingProperty = DependencyProperty.Register(nameof(IsPlaying), typeof(bool), typeof(FileInformation), new PropertyMetadata(null));
//private bool _isPlaying = false;
public bool IsPlaying
{
get => (bool)GetValue(IsPlayingProperty);
set
{
SetValue(IsPlayingProperty, value);
OnPropertyChanged();
}
}
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(nameof(Title), typeof(string), typeof(FileInformation), new PropertyMetadata(null));
public string Title
{
get => (string)GetValue(TitleProperty);
set
{
SetValue(TitleProperty, value);
OnPropertyChanged();
}
}
public TimeSpan Time
{
get { return (TimeSpan)GetValue(TimeProperty); }
set { SetValue(TimeProperty, value); }
}
public static readonly DependencyProperty TimeProperty = DependencyProperty.Register("Time", typeof(TimeSpan), typeof(FileInformation), new PropertyMetadata(null));
public event PropertyChangedEventHandler PropertyChanged;
//[NotifyPropertyChangedInvocator]
protected virtual void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberName] string propName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
public class TestConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// value = IsPlaying
if (value is bool b)
{
return b;
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
return value; // Needed because IsPlaying is twoway bound to IsSelected.
}
}
public class TimeSpanFormatConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
// value = Time
if (value is TimeSpan ts)
{
return $"{ts.Minutes} minutes {ts.Seconds} seconds";
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
如果您不希望IsSelected与IsPlaying相关联,但仍希望IsPlaying触发黄色背景,请尝试以下操作:
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<Style.Triggers>
<DataTrigger Binding="{Binding IsPlaying}" Value="True">
<Setter Property="Background" Value="Yellow" />
</DataTrigger>
</Style.Triggers>
</Style>
</ListView.ItemContainerStyle>