Wal*_*ams 4 c# wpf datagrid popup mvvm
与如何正确在 DataGridTemplateColumn.CellEditingTemplate 中放置弹出窗口相同?,我试图在编辑单元格时让 PopUp 出现在 DataGrid 中的单元格下方,并在不再编辑单元格时消失。最后一点是,PopUp 内容是根据列动态的,并且列是通过绑定动态创建的。
我从以下 XAML 开始,但收到 XamlParseException“向‘System.Windows.Controls.ItemCollection’类型的集合添加值引发了异常”。
<DataGrid ItemsSource="{Binding Path=Options}">
<DataGridTemplateColumn>
<DataGridTemplateColumn.CellEditingTemplate>
<DataTemplate>
<Grid>
<Popup Placement="Bottom" IsOpen="True" Width="200" Height="100">
<TextBlock>Somethingn here</TextBlock>
</Popup>
</Grid>
</DataTemplate>
</DataGridTemplateColumn.CellEditingTemplate>
</DataGridTemplateColumn>
</DataGrid>
Run Code Online (Sandbox Code Playgroud)
我已经找到了一个到目前为止效果很好的解决方案。它涉及一些事件处理程序,但代码不必访问视图模型,因此希望它不会招致 MVVM 纯粹主义者的愤怒。
XAML:
<Grid>
<DataGrid ItemsSource="{Binding Path=Options}" BeginningEdit="DataGrid_BeginningEdit" CellEditEnding="DataGrid_CellEditEnding" />
<Popup Name="pop1">
<Border Width="300" Height="200" Background="LemonChiffon" BorderThickness="2" BorderBrush="Black" />
</Popup>
</Grid>
Run Code Online (Sandbox Code Playgroud)
MainWindow.xaml.cs 事件处理程序:
private void DataGrid_BeginningEdit (Object sender, DataGridBeginningEditEventArgs e)
{
DataGrid grid = (DataGrid) sender;
Popup pop1 = (Popup) grid.FindName("pop1");
pop1.PlacementTarget = grid.GetCell(e.Row.GetIndex(), e.Column.DisplayIndex);
pop1.IsOpen = true;
}
private void DataGrid_CellEditEnding (Object sender, DataGridCellEditEndingEventArgs e)
{
Popup pop1 = (Popup) ((DataGrid) sender).FindName("pop1");
pop1.IsOpen = false;
}
Run Code Online (Sandbox Code Playgroud)
DataGridExtensions.cs:
/// <summary>
/// Extension methods for DataGrid
/// These methods are thanks to http://blogs.msdn.com/b/vinsibal/archive/2008/11/05/wpf-datagrid-new-item-template-sample.aspx
/// </summary>
public static class DataGridExtensions
{
/// <summary>
/// Returns a DataGridCell for the given row and column
/// </summary>
/// <param name="grid">The DataGrid</param>
/// <param name="row">The zero-based row index</param>
/// <param name="column">The zero-based column index</param>
/// <returns>The requested DataGridCell, or null if the indices are out of range</returns>
public static DataGridCell GetCell (this DataGrid grid, Int32 row, Int32 column)
{
DataGridRow gridrow = grid.GetRow(row);
if (gridrow != null)
{
DataGridCellsPresenter presenter = GetVisualChild<DataGridCellsPresenter>(gridrow);
// try to get the cell but it may possibly be virtualized
DataGridCell cell = (DataGridCell) presenter.ItemContainerGenerator.ContainerFromIndex(column);
if (cell == null)
{
// now try to bring into view and retreive the cell
grid.ScrollIntoView(gridrow, grid.Columns[column]);
cell = (DataGridCell) presenter.ItemContainerGenerator.ContainerFromIndex(column);
}
return (cell);
}
return (null);
}
/// <summary>
/// Gets the DataGridRow based on the given index
/// </summary>
/// <param name="idx">The zero-based index of the container to get</param>
public static DataGridRow GetRow (this DataGrid dataGrid, Int32 idx)
{
DataGridRow row = (DataGridRow) dataGrid.ItemContainerGenerator.ContainerFromIndex(idx);
if (row == null)
{
// may be virtualized, bring into view and try again
dataGrid.ScrollIntoView(dataGrid.Items[idx]);
dataGrid.UpdateLayout();
row = (DataGridRow) dataGrid.ItemContainerGenerator.ContainerFromIndex(idx);
}
return (row);
}
private static T GetVisualChild<T> (Visual parent) where T : Visual
{
T child = default(T);
Int32 numvisuals = VisualTreeHelper.GetChildrenCount(parent);
for (Int32 i = 0; i < numvisuals; ++i)
{
Visual v = (Visual) VisualTreeHelper.GetChild(parent, i);
child = v as T;
if (child == null)
child = GetVisualChild<T>(v);
else
break;
}
return child;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
11505 次 |
| 最近记录: |