绑定复选框在WPF中声明为BitArray

时间:2018-05-03 19:48:29

标签: c# wpf xaml data-binding

在尝试学习WFP的过程中,我已经完成了将一些旧的Winform应用程序移植到WPF并尝试坚持MVVM模型的任务。

在Winform应用程序中,我有一组复选框,用于更改BitArray的状态,而BitArray又通过TCP发送。简单的东西。

我如何在WPF和数据绑定中执行此操作?如何将特定复选框绑定到BitArray中的特定位?我在VM中找到了这个数据绑定到单个布尔属性的所有示例。

编辑:

我通过使用ObservableCollection>:

找到了解决方案

How to bind an ObservableCollection<bool> to a Listbox of Checkboxes in WPF

我不明白的目的是什么:

public static implicit operator Wrapper<T>(T value)
{
    return new Wrapper<T> { value = value };
}
public static implicit operator T(Wrapper<T> wrapper)
{
    return wrapper.value;
}

在包装类中,有人可以解释这是什么以及为什么需要它吗?

1 个答案:

答案 0 :(得分:3)

使用MVVM的好处是您可以根据需要查看模型。

  1. 创建一个Item类来跟踪数组中每个位的状态。
  2. 使用Item对象的可观察集合创建MVVM视图模型
  3. 在代码隐藏
  4. 中的视图模型
  5. 使用绑定信息装饰您的xaml
  6. 那就是它!享受!

    reference

    See an Screenshot

    C#

    using System.Collections;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using System.Windows;
    
    namespace DataBindingBitArray
    {
    
        /// <summary>
        /// 1. Create an Item class to track the status of each bit in the array. 
        /// </summary>
        /// <seealso cref="System.ComponentModel.INotifyPropertyChanged" />
        public class Item : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            public int BitArrayIndex { get; set; }
            public BitArray ParentBitArray { get; set; }
    
            private bool isChecked;
            public Item(int bitArrayIndex, bool isChecked, BitArray parentBitArray)
            {
                this.BitArrayIndex = bitArrayIndex;
                this.isChecked = isChecked;
                this.ParentBitArray = parentBitArray;
            }
            public bool IsChecked
            {
                get => isChecked;
                set
                {
                    if (ParentBitArray != null)
                    {
                        ParentBitArray[BitArrayIndex] = isChecked = value;
    
                        OnPropertyChanged(nameof(IsChecked));
                    }
                }
            }
            private void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    
        /// <summary>
        /// 2. Create a MVVM view model with an observable collection of your Item object
        /// </summary>
        /// <seealso cref="System.ComponentModel.INotifyPropertyChanged" />
        public class BitArrayViewModel : INotifyPropertyChanged
        {
            private readonly BitArray bitArray;
            private ObservableCollection<Item> items;
            public event PropertyChangedEventHandler PropertyChanged;
            public ObservableCollection<Item> Items
            {
                get => items;
                set
                {
                    items = value;
                    OnPropertyChanged(nameof(Items));
                }
            }
            public BitArrayViewModel(BitArray bitArray)
            {
                this.bitArray = bitArray;
    
                var query = this
                    .bitArray
                    .Cast<bool>()
                    .Select((s, i) => new Item(i, s, this.bitArray));
    
                this.Items = new ObservableCollection<Item>(query);
            }
    
            public int CountOnBits()
            {
                return this.bitArray.Cast<bool>().Count(s => s);
            }
            public int CountOffBits()
            {
                return this.bitArray.Cast<bool>().Count(s => !s);
            }
    
            protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    
        /// <summary>
        /// 3 . Databind your view model in code behind
        /// </summary>
        /// <seealso cref="System.Windows.Window" />
        /// <seealso cref="System.Windows.Markup.IComponentConnector" />
        public partial class MainWindow : Window
        {
            public BitArrayViewModel ViewModel;
    
            public MainWindow()
            {
                InitializeComponent();
    
                this.DataContext = ViewModel = new BitArrayViewModel(new BitArray(100));
    
                MessageBox.Show($"You have {ViewModel.CountOnBits()} on bits and {ViewModel.CountOffBits()} off bits");
            }
    
            private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
            {
                MessageBox.Show($"You have {ViewModel.CountOnBits()} on bits and {ViewModel.CountOffBits()} off bits");
            }
        }
    }
    

    XAML

    <Window x:Class="DataBindingBitArray.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:DataBindingBitArray"
            mc:Ignorable="d"
            Height="360" Width="250">
        <StackPanel Height="300" Margin="10">
            <Label Height="40"  Margin="5" FontSize="18">Binding to Bit Array</Label>
            <ScrollViewer Height="200">
                <ItemsControl  Margin="5" x:Name="ItemsControl1" ItemsSource="{Binding Path=Items}"  HorizontalAlignment="Stretch">
                    <ItemsControl.ItemTemplate>
                        <DataTemplate>
                            <CheckBox IsChecked="{Binding Path=IsChecked, Mode=TwoWay}" Content ="{Binding Path=BitArrayIndex }"/>
                        </DataTemplate>
                    </ItemsControl.ItemTemplate>
                </ItemsControl>
            </ScrollViewer>
            <Button Height="40" Margin="5" Click="ButtonBase_OnClick" Content="Show BitArray Status"></Button>
        </StackPanel>
    </Window>