开发者

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;
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜