Control per bit binding to large bitset
Lets say I got a large bitset (class doesn't matter, can be bool[100]) and I got 10x10 rectangles of colors black and white which I want to bind to each individual bit in my bitset.
I also want not to force full redraw when single bit changes (there are some solutions which can lead to this behaviour) but only a single redraw of that specific rectangle.
Any other details about my actual implementations don't matter, I can u开发者_开发百科se any class that will suit best to store those bits (ObservableCollection, smth else, you name it).
I'd prefer most elegant solution , I would also prefer not to blowup viewmodel with 100 properties.. and huge case method.
This was a fun question to test a solution for. :)
Here is what I came up with. Click the play button to watch the colors randomize.
View:
<UserControl
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:vm="clr-namespace:Samples.ViewModels"
xmlns:toolkit="http://schemas.microsoft.com/winfx/2006/xaml/presentation/toolkit" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Class="Samples.BitsetView"
mc:Ignorable="d"
d:DesignHeight="400" d:DesignWidth="500">
<UserControl.Resources>
<vm:BitsetViewModel x:Key="vm" />
<ItemsPanelTemplate x:Key="ItemsPanelTemplate">
<toolkit:WrapPanel />
</ItemsPanelTemplate>
<DataTemplate x:Key="ItemTemplate">
<Rectangle Width="10" Height="10" Fill="{Binding Brush}"/>
</DataTemplate>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White" DataContext="{StaticResource vm}" Width="500" Height="400">
<ItemsControl Margin="0" ItemsSource="{Binding Bitset}" ItemsPanel="{StaticResource ItemsPanelTemplate}" ItemTemplate="{StaticResource ItemTemplate}"/>
<Button Content="{Binding Action}" Height="23" Width="40" HorizontalAlignment="Center" VerticalAlignment="Bottom">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="Play"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</UserControl>
And the ViewModel:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows.Media;
using System.Windows.Threading;
namespace Samples.ViewModels
{
public class BitsetViewModel
{
private List<BitsetItem> _bitset = new List<BitsetItem>();
private Random _rand = new Random();
private DispatcherTimer _timer = new DispatcherTimer();
public BitsetViewModel()
{
_timer.Interval = TimeSpan.FromMilliseconds(1);
_timer.Tick += new EventHandler(_timer_Tick);
for (int i = 0; i < 2000; i++)
{
var color = _rand.Next(0, 5);
_bitset.Add(new BitsetItem() { Color = color == 1 ? Colors.Black : Colors.White });
}
}
void _timer_Tick(object sender, EventArgs e)
{
var bit = _rand.Next(0, 1999);
_bitset[bit].Color = _bitset[bit].Color == Colors.White ? Colors.Black : Colors.White;
}
public IEnumerable<BitsetItem> Bitset
{
get {return _bitset;}
}
public string Action
{
get { return _timer.IsEnabled ? "Stop" : "Play"; }
}
public void Play()
{
if (_timer.IsEnabled)
_timer.Stop();
else
_timer.Start();
}
}
public class BitsetItem : INotifyPropertyChanged
{
private Color _color = Colors.White;
private SolidColorBrush _brush = new SolidColorBrush();
public Color Color
{
get { return _color; }
set
{
_color = value;
_brush = new SolidColorBrush(Color);
RaisePropertyChanged("Color");
RaisePropertyChanged("Brush");
}
}
public SolidColorBrush Brush
{
get { return _brush; }
set
{
_brush = value;
RaisePropertyChanged("Brush");
}
}
private void RaisePropertyChanged(string name)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
}
}
精彩评论