我的数据网格中有一个奇怪的效果。在此示例中,datagrid有200行,第一列有递增索引。 datagrid有一个MaxHeight属性,所以我只看到加载前30行。
我可以向下滚动200行,但我从未在第一列中看到数字30-200只重复0-29!?! (我检查了该集合是否具有正确的值)
如果我将DataGridTemplateColumn中的列更改为DataGridTextColumn,我会看到所有值,但这不是我想要的。
有人知道,为什么单元格内容没有显示正确的值?
这是我的代码。这是大型MVVM项目的简化示例。请对这种结构宽容。
<Window.Resources>
<local:RowCellConverter x:Key="rcconv" />
<DataTemplate DataType="{x:Type local:BusinessDataGrid}">
<Grid
Margin="5"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Transparent"
Focusable="False"
Visibility="Visible">
<DataGrid
Name="dataGrid"
Height="700"
MaxHeight="600"
AutoGenerateColumns="False"
CanUserAddRows="False"
CanUserDeleteRows="False"
CanUserReorderColumns="False"
CanUserResizeColumns="True"
CanUserResizeRows="False"
CanUserSortColumns="False"
ColumnWidth="*"
EnableColumnVirtualization="True"
EnableRowVirtualization="True"
Initialized="dataGrid_Initialized"
ItemsSource="{Binding rows}"
ScrollViewer.CanContentScroll="True"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.VerticalScrollBarVisibility="Auto"
SelectionMode="Single"
SelectionUnit="CellOrRowHeader">
<DataGrid.Resources>
<DataTemplate x:Key="MyFieldCell" DataType="DataGridTemplateColumn">
<StackPanel>
<TextBlock Background="LightSalmon">Hallo</TextBlock>
<TextBox
x:Name="TableCell"
DataContext="{Binding RelativeSource={RelativeSource AncestorType=DataGridCell}, Converter={StaticResource rcconv}}"
IsReadOnly="False"
Background="{Binding Path=StateColor}"
Text="{Binding Path=MyValue}" />
</StackPanel>
</DataTemplate>
</DataGrid.Resources>
</DataGrid>
</Grid>
</DataTemplate>
</Window.Resources>
<Grid>
<ItemsControl Name="iControl" ItemsSource="{Binding Path=MainWindow.bFields}" />
</Grid>
背后的代码:
public partial class MainWindow : Window
{
public ObservableCollection<BusinessField> bFields = new ObservableCollection<BusinessField>();
public MainWindow()
{
BusinessDataGrid bdg = new BusinessDataGrid();
foreach (string col in new string[] { "Col1", "Col2", "Col3", "Col4", "Col5", "Col6", })
{
bdg.cols.Add(col);
}
for (int i = 0; i < 200; i++)
{
FieldRow fr = new FieldRow();
foreach(string col in bdg.cols)
{
FieldCell fc = new FieldCell();
fc.MyValue = string.Format("{0:000}{1}", i, col);
fr.cells.Add(fc);
}
bdg.rows.Add(fr);
}
InitializeComponent();
ItemsControl ic = iControl;
ic.ItemsSource = bFields;
bFields.Add(bdg);
}
private void dataGrid_Initialized(object sender, EventArgs e)
{
DataGrid dg = sender as DataGrid;
if (dg != null)
{
BusinessDataGrid bdg = dg.DataContext as BusinessDataGrid;
if (bdg != null)
bdg.OnUIInitialized(dg);
}
}
}
public class BusinessField : INotifyPropertyChanged
{
private PropertyChangedEventHandler propertyChangedEvent;
public void SendPropertyChanged(string propertyName)
{
VerifyCalledOnUIThread();
if (propertyChangedEvent != null)
propertyChangedEvent(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged
{
add
{
VerifyCalledOnUIThread();
propertyChangedEvent += value;
}
remove
{
VerifyCalledOnUIThread();
propertyChangedEvent -= value;
}
}
[Conditional("Debug")]
protected void VerifyCalledOnUIThread()
{
Debug.Assert(Dispatcher.CurrentDispatcher == Dispatcher.CurrentDispatcher, "Call must be made on UI thread.");
}
}
public class BusinessDataGrid:BusinessField
{
public List<string> cols = new List<string>();
public ObservableCollection<FieldRow> rows = new ObservableCollection<FieldRow>();
public void OnUIInitialized(DataGrid datagrid)
{
DataTemplate dt = (DataTemplate)datagrid.Resources["MyFieldCell"];
datagrid.Columns.Clear();
foreach(string col in cols)
{
DataGridTemplateColumn dgtc = new DataGridTemplateColumn()
{
CellTemplate = dt,
Visibility = Visibility.Visible,
Header = col,
SortMemberPath=col,
};
datagrid.Columns.Add(dgtc);
}
datagrid.ItemsSource = rows;
}
}
public class RowCellConverter : IValueConverter
{
#region IValueConverter Members
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
DataGridCell cell = value as DataGridCell;
if((string)parameter == "FieldCell")
{
}
if (cell == null)
return null;
DataGridCellsPresenter dgcp = TreeHelper.GetVisualParent<DataGridCellsPresenter>(cell);
int ci = dgcp.ItemContainerGenerator.IndexFromContainer(cell);
FieldRow fr = cell.DataContext as FieldRow;
if (fr == null)
return null;
object ret = null;
switch((string)parameter)
{
case "StateColor":
ret = fr.cells[ci].StateColor;
break;
case "MyValue":
ret = fr.cells[ci].MyValue;
break;
default:
ret = fr.cells[ci];
break;
}
return ret;
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class TreeHelper
{
#endregion
public static T GetVisualChild<T>(DependencyObject obj) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(obj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(obj, i);
if (child != null && child is T)
return (T)child;
else
{
T childOfChild = GetVisualChild<T>(child);
if (childOfChild != null)
return childOfChild;
}
}
return null;
}
public static T GetVisualParent<T>(DependencyObject child) where T : DependencyObject
{
//get parent item
DependencyObject parentObject = VisualTreeHelper.GetParent(child); //we’ve reached the end of the tree
if (parentObject == null) return null;
//check if the parent matches the type we’re looking for
T parent = parentObject as T;
if (parent != null)
return parent;
else
return GetVisualParent<T>(parentObject);
}
}
public enum FieldCellState
{
Ok,
Error
}
public class FieldRow
{
public ObservableCollection<FieldCell> cells = new ObservableCollection<FieldCell>();
}
public class FieldCell : INotifyPropertyChanged
{
public string Colname;
private string myValue;
public override string ToString()
{
return MyValue;
}
public string MyValue
{
get { return myValue; }
set { myValue = value; }
}
public FieldCellState MyState
{
get { return (MyValue.Contains("7")) ? FieldCellState.Error : FieldCellState.Ok; }
}
public Brush StateColor
{
get { return (MyState == FieldCellState.Ok) ? new SolidColorBrush(Colors.LightGreen) : new SolidColorBrush(Colors.LightSalmon); }
}
private PropertyChangedEventHandler propertyChangedEvent;
public void SendPropertyChanged(string propertyName)
{
VerifyCalledOnUIThread();
if (propertyChangedEvent != null)
propertyChangedEvent(this, new PropertyChangedEventArgs(propertyName));
}
public event PropertyChangedEventHandler PropertyChanged
{
add
{
VerifyCalledOnUIThread();
propertyChangedEvent += value;
}
remove
{
VerifyCalledOnUIThread();
propertyChangedEvent -= value;
}
}
[Conditional("Debug")]
protected void VerifyCalledOnUIThread()
{
Debug.Assert(Dispatcher.CurrentDispatcher == Dispatcher.CurrentDispatcher, "Call must be made on UI thread.");
}
}
答案 0 :(得分:0)
这是因为你启用了这两个选项
EnableColumnVirtualization="True"
EnableRowVirtualization="True"
它会尝试为您虚拟化它。尝试将它们设为False,看看你是否能正确看到你的内容。请记住将它们设置为false会导致DataGrid
加载速度变慢。
尝试为每列执行此操作,而不是在资源级别创建模板。这只是一个例子,您可以根据自己的风格进行调整。
<DataGridTemplateColumn Header="Some Name" IsReadOnly="False" Width="*">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<RichTextBox>
<FlowDocument IsOptimalParagraphEnabled="True" IsHyphenationEnabled="True">
<Paragraph FontFamily="Segoe UI" FontSize="14">
<Run Text="{Binding Path=First ,Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}" />
<Run Text="{Binding Path=FirstText ,Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}" />
<Run Text="{Binding Path=SearchedText ,Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}" Background="#FFE34C"/>
<Run Text="{Binding Path=SecondText ,Mode=TwoWay , UpdateSourceTrigger=PropertyChanged}" />
</Paragraph>
</FlowDocument>
</RichTextBox>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
答案 1 :(得分:-1)
好像你在使用第三方网格?问题是如何虚拟化
我有一次这个问题,原因是我正在使用网格的标识列,因此该列是自动生成的。
网格正在虚拟化,因此无法计算视图上方或下方的行数。
如果你不需要它可以停止虚拟化(200行左右不会有任何区别)
或添加一个绑定到集合中项目索引的新列,该列应该可以正常工作