C# 在WPF网格中显示带索引的一维数组
我有一个双值的一维数组 使用WPF,在具有两列数组索引(第一列)和数组值(第二列)的网格中显示值的最佳方式是什么 第一列是只读的,但第二列应该是可编辑的 事实上,数据表示固定频率(例如20kHz)下基于时间的值序列。我可以将每个样本的时间计算为(开始时间+索引/频率) 用索引、时间和数据三列显示数据的最佳方式是什么?我找到了基本思路 我定义了两个转换器,一个用于索引C# 在WPF网格中显示带索引的一维数组,c#,.net,arrays,wpf,datagrid,C#,.net,Arrays,Wpf,Datagrid,我有一个双值的一维数组 使用WPF,在具有两列数组索引(第一列)和数组值(第二列)的网格中显示值的最佳方式是什么 第一列是只读的,但第二列应该是可编辑的 事实上,数据表示固定频率(例如20kHz)下基于时间的值序列。我可以将每个样本的时间计算为(开始时间+索引/频率) 用索引、时间和数据三列显示数据的最佳方式是什么?我找到了基本思路 我定义了两个转换器,一个用于索引 public class IndexConverter : IValueConverter { public object C
public class IndexConverter : IValueConverter
{
public object Convert(object value, Type TargetType, object parameter, CultureInfo culture)
{
ListViewItem item = (ListViewItem) value;
ListView listView = ItemsControl.ItemsControlFromItemContainer(item) as ListView;
int index = listView.ItemContainerGenerator.IndexFromContainer(item);
return index.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
第一次是一个
public class SampleTimeConverter : IValueConverter
{
private double StartTime = 0.0 ;
private double SamplingRate = 20000.0 ;
public object Convert(object value, Type TargetType, object parameter, CultureInfo culture)
{
ListViewItem item = (ListViewItem) value;
ListView listView = ItemsControl.ItemsControlFromItemContainer(item) as ListView;
int index = listView.ItemContainerGenerator.IndexFromContainer(item);
double sampleTime = StartTime + index / SamplingRate ;
return String.Format ( "{0:F5}", sampleTime ) ;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
稍后,我将通过StartTime和SamplingRate作为属性
对于这个测试,我定义了一个ViewModel,其属性为public double[]MyData
在XAML中,我定义了一个ListView,如下所示:
<Window.Resources>
<local:IndexConverter x:Key="IndexConverter"/>
<local:SampleTimeConverter x:Key="SampleTimeConverter"/>
</Window.Resources>
<Grid>
<ListView Name="listviewNames" ItemsSource="{Binding MyData}">
<ListView.View>
<GridView>
<GridView.Columns>
<GridViewColumn Header="Index" Width="100"
DisplayMemberBinding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListViewItem}},
Converter={StaticResource IndexConverter}}" />
<GridViewColumn Header="Time" Width="200"
DisplayMemberBinding="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType={x:Type ListViewItem}},
Converter={StaticResource SampleTimeConverter}}" />
<GridViewColumn Header="Value" Width="auto" >
<GridViewColumn.CellTemplate>
<DataTemplate>
<TextBox Text="{Binding Mode=OneWay}" Width="200" BorderThickness="0"/>
</DataTemplate>
</GridViewColumn.CellTemplate>
</GridViewColumn>
</GridView.Columns>
</GridView>
</ListView.View>
</ListView>
</Grid>
这或多或少是在做我想做的事
我还没有测试是否将编辑的值写回数组。事实上,我非常确定bindingmode=OneWay是错误的,但我认为我会找到解决方法
我唯一的疑问是,为每个值(可能有数千个)创建一个文本框是否会导致性能问题。我的第一个解决方案非常适合显示只读数据 根据我目前的理解,编辑双值数组是不可能的。要编辑值,必须使用setter和getter方法将其定义为属性 我真的不想这样做,因为这意味着为数组中的每个元素创建一个单独的对象。但是,如果我这样做,剩下的就很容易了,我可以不用第一个解决方案中使用的值转换器 我已经为网格中的每个项目定义了一个类:
public class DataItem
{
int _index ;
double _sampleTime ;
ViewModel _vm ;
public DataItem ( int Index, double SampleTime, ViewModel vm )
{
_index = Index ;
_sampleTime = SampleTime ;
_vm = vm ;
}
public int Index
{
get { return _index ; }
}
public double SampleTime
{
get { return _sampleTime ; }
}
public double Value
{
get { return _vm.MyData[_index] ; }
set { _vm.MyData[_index] = value ; }
}
}
我在一个简单的循环中创建视图模型中的对象。为了简单起见,我将索引和时间作为参数传入。我传入对ViewModel的引用,以便数组值的setter可以将编辑后的值存储回原始数组中
_items = new List<DataItem>() ;
for ( int i = 0 ; i < darray.Length ; i++ )
{
_items.Add ( new DataItem ( i, startTime + samplingRate * i, this ) ) ;
}
\u items=新列表();
for(int i=0;i
我把这段代码放在ViewModel的构造函数中,这对我来说已经足够好了。ViewModel具有返回集合的Items属性
在XAML中,我使用了DataGrid,因为它支持直接编辑
<DataGrid x:Name="ValuesGrid"
ItemsSource="{Binding Items}"
AutoGenerateColumns="False"
CanUserReorderColumns="False"
CanUserResizeRows="False"
CanUserAddRows="False"
HorizontalGridLinesBrush="DarkGray"
VerticalGridLinesBrush="DarkGray"
>
<DataGrid.Columns>
<DataGridTextColumn Header="Index" Binding="{Binding Index}" Width="10*" IsReadOnly="True"/>
<DataGridTextColumn Header="Time" Binding="{Binding SampleTime}" Width="20*" IsReadOnly="True"/>
<DataGridTextColumn Header="Value" Binding="{Binding Value}" Width="20*" IsReadOnly="False"/>
</DataGrid.Columns>
</DataGrid>
最后,我想重复一遍。这个问题的答案是“你做不到”。双向绑定到double数组是不可能的。必须使用setter和getter方法将每个项包装在对象中