我一直在寻找一种方法来存储数字作为对象的属性,并在Windows Presentation Foundation中将其位模式显示为一系列复选框。这是我现在使用的方法,当选中复选框时,它会更新数值,并且当数字更改时复选框会更新。如果能以更简单的方式实现,请告诉我。
MainWindow.xaml.cs
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Media;
using System.Windows;
using System.Windows.Controls;
namespace WPF_Interface_Tests
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public BitField BF { get; set; }
public MainWindow()
{
InitializeComponent();
DataContext = this;
BF = new BitField(0, 32);
}
private void Plus_Click(object sender, RoutedEventArgs e)
{
if (BF.Value < uint.MaxValue)
BF.Value += 1;
}
private void Minus_Click(object sender, RoutedEventArgs e)
{
if (BF.Value > uint.MinValue)
BF.Value -= 1;
}
private void CheckBox_Click(object sender, RoutedEventArgs e)
{
SystemSounds.Beep.Play();
var a = (CheckBox)sender;
int checkity = 0;
if (a.IsChecked.Value)
checkity = 1;
BF.Value = BF.Value | (uint)(checkity << (int)a.Tag);
}
}
public class Bit : INotifyPropertyChanged
{
private bool state;
public bool State { get { return state; } set { if (this.state != value) { this.state = value; NotifyPropertyChanged("State"); } } }
public int Index { get; set; }
public Bit()
{
State = false;
Index = 0;
}
public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged(string propName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); }
}
public class BitField : INotifyPropertyChanged
{
private uint value;
public uint Value { get { return value; } set { if (this.value != value) { this.value = value; NotifyPropertyChanged("Value"); UpdateValues(); } } }
public byte ByteSize { get; set; }
public ObservableCollection<Bit> Values { get; set; }
public BitField(uint givenValue, byte givenByteSize)
{
Value = givenValue;
ByteSize = givenByteSize;
Values = new ObservableCollection<Bit>();
for (int i = 0; i < ByteSize; i++)
{
if ((Value | (uint)(1 << i)) == Value)
Values.Add(new Bit { State = true, Index = i });
else
Values.Add(new Bit { State = false, Index = i });
}
}
private void UpdateValues()
{
for (int i = 0; i < Values.Count; i++)
{
if ((Value | (uint)(1 << i)) == Value)
Values[i].State = true;
else
Values[i].State = false;
}
}
public event PropertyChangedEventHandler PropertyChanged; public void NotifyPropertyChanged(string propName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName)); }
}
}
MainWindow.xaml
<Window x:Class="WPF_Interface_Tests.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:WPF_Interface_Tests"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="10,201,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Path=BF.Value, UpdateSourceTrigger=PropertyChanged}"/>
<Button x:Name="Minus" Content="-" HorizontalAlignment="Left" Margin="10,229,0,0" VerticalAlignment="Top" Width="20" Click="Minus_Click" />
<ListBox x:Name="LBofChecks" HorizontalAlignment="Left" Height="186" Margin="10,10,0,0" VerticalAlignment="Top" Width="100" ItemsSource="{Binding Path=BF.Values, UpdateSourceTrigger=PropertyChanged}">
<ListBox.ItemTemplate>
<DataTemplate>
<CheckBox IsChecked="{Binding Path=State, Mode=TwoWay}" Tag="{Binding Path=Index}" Click="CheckBox_Click"/>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button x:Name="Plus" Content="+" HorizontalAlignment="Left" Margin="35,229,0,0" VerticalAlignment="Top" Width="20" Click="Plus_Click" />
</Grid>
</Window>
我的方法涉及使用新颖的BitField
对象作为主窗口的属性。我设置DataContext = this
然后构造BitField
属性。
BitField
通知其Value
属性何时更改。 Value
属性存储表示位序列的数字。对于要用作绑定到复选框的属性的值列表,我给BitField
一个ObservableCollection<Bit> Values
属性。 Bit
个对象的集合也会在其State
bool属性发生更改时通知每个对象。我还存储Bit
Index
Bit
对象在ObservableCollection<Bit> Values
内的每个CheckBox
。您可以在.xaml文件的Tag
模板中看到,我将复选框的Index
属性与其Bit
的{{1}}相关联。
是否有更简单的方法?
答案 0 :(得分:4)
在ViewModel方面,我只是暴露一个整数/字节属性进行绑定 - 例如int为32位值。称之为&#34; MyValue&#34;讨论。是的,当它发生变化时仍然会通知。
在View方面,我会双向绑定&#34; IsChecked&#34;每个Checkbox权限到MyValue的属性。对于&#34; bit&#34;绑定你会使用转换器,例如称之为BinaryValueToBitConverter
。
转换器接受一个int(或字节等),并为每个Checkbox将其转换为true false。关键是,对于每个复选框,您使用复选框的位位置作为ConverterParameter
,转换器的转换()方法就是:
return (value & (1 << bitParam)) != 0;
在哪里&#34; bitParam&#34;是传递的ConverterParameter(当然)。
您可能会找到一种方法来使用其父控件的CheckBox的子索引,例如StackPanel / ListBox作为ConverterParameter。
希望有用