I have a listview with values that are being updated constantly from a different thread. I want to change the color of the background according to the value of the item. After reading a lot I came to the following conclusions:
How can I achieve this simple behavior?
xaml:
<Page
x:Class="MyProject.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:MyProject"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<ListView ItemsSource="{x:Bind ViewModel.DataRef.Values, Mode=OneWay}" HorizontalAlignment="Center" VerticalAlignment="Center">
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:ValWrapper">
<TextBlock Text="{x:Bind Val, Mode=OneWay}"/>
</DataTemplate>
</ListView.ItemTemplate>
<ListView.ItemContainerStyleSelector>
<local:CustomItemContainerStyleSelector>
<local:CustomItemContainerStyleSelector.Bad>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="Red"/>
</Style>
</local:CustomItemContainerStyleSelector.Bad>
<local:CustomItemContainerStyleSelector.Good>
<Style TargetType="ListViewItem">
<Setter Property="Background" Value="Green"/>
</Style>
</local:CustomItemContainerStyleSelector.CloseToBad>
</local:CustomItemContainerStyleSelector>
</ListView.ItemContainerStyleSelector>
</ListView>
</Grid>
</Page>
cs:
public sealed partial class MainPage : Page
{
public ViewModel ViewModel { get; set; }
public MainPage()
{
this.InitializeComponent();
this.ViewModel = new ViewModel();
}
}
public class CustomItemContainerStyleSelector : StyleSelector
{
public Style Bad { get; set; }
public Style Good { get; set; }
protected override Style SelectStyleCore(object item, DependencyObject container)
{
double threshold = 1;
ValWrapper v = (ValWrapper)item;
if (v.Val <= threshold)
{
return Bad;
}
else {
return Good;
}
}
}
Whenever the data changes, "NotifyPropertyChanged" is called (implements INotifyPropertyChanged).
Please check the following steps:
_tempValue
to record previous number.Background
property to IsUpdate
, the initial value is all false
.IsUpdate
to true
, then the Background
of ListViewItem
turns red
.XAML:
<Page
x:Class="Permisson.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Permisson"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Page.Resources>
<local:ColorConverter x:Key="ColorConverter"/>
</Page.Resources>
<Grid>
<StackPanel>
<ListView ItemsSource="{x:Bind ViewModel.DataRef, Mode=OneWay}" HorizontalAlignment="Center" VerticalAlignment="Center">
<ListView.ItemTemplate >
<DataTemplate x:DataType="local:ValWrapper">
<Grid Background="{Binding IsUpdate, Converter={StaticResource ColorConverter},Mode=OneWay}">
<TextBlock Text="{Binding Val, Mode=OneWay}"/>
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Content="ChangeNum" Click="Button_Click"/>
<Button Content="ChangeNum2" Click="Button_Click_1"/>
</StackPanel>
</Grid>
</Page>
Code behind:
namespace Permisson
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
public ViewModel ViewModel { get; set; }
public MainPage()
{
this.InitializeComponent();
this.ViewModel = new ViewModel();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var v = ViewModel.DataRef[0];
v.Val = 9;
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
var v = ViewModel.DataRef[1];
v.Val = 10;
}
}
public class ViewModel
{
private ObservableCollection<ValWrapper> dataRef = new ObservableCollection<ValWrapper>()
{
new ValWrapper {Val=22,Brush=new SolidColorBrush (Colors.Green),IsUpdate = false },
new ValWrapper {Val=25,Brush=new SolidColorBrush (Colors.Green),IsUpdate = false},
new ValWrapper {Val=35,Brush=new SolidColorBrush (Colors.Green),IsUpdate = false},
new ValWrapper {Val=45,Brush=new SolidColorBrush (Colors.Green),IsUpdate = false },
new ValWrapper {Val=55,Brush=new SolidColorBrush (Colors.Green),IsUpdate = false},
new ValWrapper {Val=65,Brush=new SolidColorBrush (Colors.Green),IsUpdate = false }
};
public ObservableCollection<ValWrapper> DataRef { get { return dataRef; } }
}
public class ColorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, string language)
{
var color = new SolidColorBrush();
if ((bool)value)
{
color.Color = Colors.Red;
}
else
{
color.Color = Colors.Green;
}
return color;
}
public object ConvertBack(object value, Type targetType, object parameter, string language)
{
throw new NotImplementedException();
}
}
public class ValWrapper : INotifyPropertyChanged
{
private int val;
private SolidColorBrush brush;
public SolidColorBrush Brush
{
get { return brush; }
set
{
brush = value;
RaisePropertyChanged();
}
}
private int _tempValue;
public int Val
{
get { return val; }
set
{
if(_tempValue != value && _tempValue != 0)
{
IsUpdate = true;
}
val = value;
RaisePropertyChanged();
_tempValue = val;
}
}
private bool _isUpdate;
public bool IsUpdate
{
set
{
_isUpdate = value;
RaisePropertyChanged();
}
get
{
return _isUpdate;
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void RaisePropertyChanged([CallerMemberName] string propertyname = null)
{
PropertyChangedEventHandler handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyname));
}
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.