【问题标题】:Show popup during editing of WPF DataGrid cell在编辑 WPF DataGrid 单元格期间显示弹出窗口
【发布时间】:2014-01-08 21:26:57
【问题描述】:

How do I place a Popup in my DataGridTemplateColumn.CellEditingTemplate correctly? 相同,我试图在编辑单元格时在 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>

【问题讨论】:

标签: c# wpf mvvm datagrid popup


【解决方案1】:

到目前为止,我已经找到了一个行之有效的解决方案。它涉及一些事件处理程序,但代码不必访问视图模型,因此希望它不会引起 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>

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;
}

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;
    }
}

【讨论】:

    【解决方案2】:

    我相信一个好的方法是像这样设置它

    <Grid>
        <DataGrid Name="DataGridList" ItemsSource="{Binding SettingsList, Mode=TwoWay}" AutoGenerateColumns="False" Height="146">
            <!--Resources-->
            <DataGrid.Resources>               
                <!--DataTemplate-->
                <DataTemplate x:Key="DateTemplate" >
                    <StackPanel>
                        <TextBlock Text="{Binding YourBinding}"></TextBlock>
                    </StackPanel>
                </DataTemplate>              
                <!--EditingDateTemplate-->
                <DataTemplate x:Key="EditingDateTemplate">
                    <Grid>
                        <Popup Placement="Bottom" IsOpen="True" Width="200" Height="100">
                            <TextBlock>Something here</TextBlock>
                        </Popup>
                    </Grid>
                </DataTemplate>
            </DataGrid.Resources>
            <!--Datagrid-->
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="header 1" CellTemplate="{StaticResource DateTemplate}" CellEditingTemplate="{StaticResource EditingDateTemplate}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
    

    【讨论】:

    • 这似乎做了一些添加行的奇怪行为,并没有创建我的动态列;我也不希望用弹出窗口替换正常的单元格编辑行为,而是让弹出窗口显示补充信息。
    猜你喜欢
    • 2011-12-06
    • 2019-02-24
    • 2015-11-07
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-27
    相关资源
    最近更新 更多