我刚刚发现由于我的类中的索引不匹配而导致的一个潜在的错误,这是由于代码重复和序列化。
我的问题:是否会有另一种更明智的方式来公开属性(与WPF一起用于数据绑定)而没有所有这些可怕的重复?
代码(对最差部分的评论):
public class MemoryTable
{
public string Name { get; private set; }
int TableNumber { get; set; }
DeviceWrapper _device;
public MemoryTable(DeviceWrapper deviceWrapper, string name, int number)
{
_device = deviceWrapper;
Name = name;
TableNumber = number;
}
public float P1
{
get { return getVal(0); }
set { setVal(0, value); }
}
public float P2
{
get { return getVal(1); }
set { setVal(1, value); }
}
public float P3 // Notice that I have three numerical values
{
get { return getVal(2); }
set { setVal(2, value); } // I typed "1" here accidentally... Bug!
}
public float P4
{
get { return getVal(3); }
set { setVal(3, value); }
}
public float P5
{
get { return getVal(4); }
set { setVal(4, value); }
}
public float P6
{
get { return getVal(5); }
set { setVal(5, value); }
}
public float P7
{
get { return getVal(6); }
set { setVal(6, value); }
}
public float P8
{
get { return getVal(7); }
set { setVal(7, value); }
}
private float getVal(int pos)
{
return _device.GetCalibrationValue(TableNumber, pos);
}
private void setVal(int pos, float val)
{
_device.SetCalibrationValue(TableNumber, pos, val);
}
internal void FillWithValue(float value)
{
P1 = value;
P2 = value;
P3 = value;
P4 = value;
P5 = value;
P6 = value;
P7 = value;
P8 = value; // "foreach" by hand, really? :o(
}
}
编辑:XAML,接受了答案的建议:
<DataGrid.Columns>
<DataGridTextColumn Header="A1" Binding="{Binding [0]}" Width="100"/>
<DataGridTextColumn Header="B1" Binding="{Binding [1]}" Width="100"/>
<DataGridTextColumn Header="A2" Binding="{Binding [2]}" Width="100"/>
<DataGridTextColumn Header="B2" Binding="{Binding [3]}" Width="100"/>
<DataGridTextColumn Header="A3" Binding="{Binding [4]}" Width="100"/>
<DataGridTextColumn Header="B3" Binding="{Binding [5]}" Width="100"/>
<DataGridTextColumn Header="A4" Binding="{Binding [6]}" Width="100"/>
<DataGridTextColumn Header="B4" Binding="{Binding [7]}" Width="100"/>
</DataGrid.Columns>
答案 0 :(得分:4)
您可以绑定到索引属性:
public float this[int i]
{
get { return getVal(i); }
set { setVal(i, value); }
}
在XAML中:
<!-- If MemoryTable instance is property of current data context -->
<TextBox Text="{Binding MyMemoryTable[1]}" />
<!-- If MemoryTable instance itself is current data context -->
<TextBox Text="{Binding [1]}" />
答案 1 :(得分:1)
我可以想到几种不同的方式,但我并不特别喜欢它们。
一种方法是将属性实现为索引器:
public float this[int index]
{
get { return getVal(index); }
set { setVal(index, value); }
}
您需要添加范围检查,因为有人可能会尝试myObject[7]
并且不应该允许这样做。{1}}您可以绑定到WPF中的索引器。这样可能工作。但它确实将责任推给了你班级的消费者,因为他们不会获得属性的智能感知(因为它只是一个不可或缺的参数)。
另一个选项会涉及一些带有反射的技巧,以获取要设置的属性的名称,并使用它来确定要传递到getVal
/ setVal
的值。但这至少得到了反思和字符串解析,感觉......错了。但这类似于使用C#6中的CallerMemberNameAttribute或nameof
运算符。