WPF Popup专注于数据网格

时间:2009-11-23 18:14:40

标签: wpf datagrid popup focus

我正在创建一个在DataGrid编辑模板中使用的自定义UserControl。 它看起来像这样:

<UserControl
   x:Class="HR.Controls.UserPicker"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:tk="http://schemas.microsoft.com/wpf/2008/toolkit"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <Grid>
        <TextBlock x:Name="PART_TextBox" Text="Hello WOrld" />
        <Popup Width="234" Height="175" IsOpen="True" StaysOpen="True"

             Placement="Bottom"
             PlacementTarget="{Binding ElementName=PART_TextBox}"
         >
            <TextBox
                  x:Name="searchTextBox"
                  Text="&gt;Enter Name&lt;"/>
        </Popup>
    </Grid>
</UserControl>

修改 我已经缩小了代码的范围。 看来,如果我将一个带有文本框的Popup直接放在CellEditingTemplate中,那么文本框得到的焦点就没问题了。当我将该代码移动到UserControl中时,我在编辑单元格时无法再选择文本框。

UserControl是否以焦点做了一些有趣的事情?


问题是当我在datagrid中编辑单元格时,我得到了用户控件,但我无法单击TextBox searchTextBox。当我点击它时,弹出窗口关闭,单元格恢复默认状态。

我已经尝试复制并粘贴用户控件中的所有代码,并将其直接粘贴到CellEditingTemplate中,并以它应该的方式进行交互。

我只是想知道UserControl是否做了一些奇怪的事情,阻止弹出窗口获得焦点,因为它直接放在CellEditingTemplate中时按预期工作?

谢谢, 劳尔

4 个答案:

答案 0 :(得分:3)

我遇到了类似的问题,其中Popup嵌入UserControl作为单元格编辑模板会在单击某些区域时关闭。结果问题是WPF工具包(可能是WPF4)DataGrid非常贪婪,只需点击鼠标左键。即使处理它们并将Handled设置为true,网格也可以将它们解释为单击另一个单元格。

thread包含完整的详细信息,但修复方法是挂钩DataGrid.CellEditEnding事件并取消结束编辑:

private static void DataGrid_CellEditEnding(object sender, DataGridCellEditEndingEventArgs e)
{
    if (e.Column.GetType() == typeof(DataGridTemplateColumn))
    {
        var popup = GetVisualChild<Popup>(e.EditingElement);
        if (popup != null && popup.IsOpen)
        {
            e.Cancel = true;
        }
    }   
}

private static T GetVisualChild<T>(DependencyObject visual)
    where T : DependencyObject
{
    if (visual == null)
        return null;

    var count = VisualTreeHelper.GetChildrenCount(visual);
    for (int i = 0; i < count; i++)
    {
        var child = VisualTreeHelper.GetChild(visual, i);

        var childOfTypeT = child as T ?? GetVisualChild<T>(child);
        if (childOfTypeT != null)
            return childOfTypeT;
    }

    return null;
}

完全归功于Actipro thread

答案 1 :(得分:3)

不确定这是否会对任何人有所帮助,但如果您在数据网格中使用弹出窗口有自定义控件,这会有所帮助......这解决了我的问题,而且它是一行xaml。我花了一整天重新阅读这个论坛,然后查看DataGridCell的源代码。希望这会有所帮助。

    <Style TargetType="{x:Type DataGridCell}">
        <Setter Property="Focusable" Value="False"></Setter>
    </Style>

答案 2 :(得分:2)

我有一个类似的问题,我创建了一个包含文本框,按钮和日历的用户控件。 Basicaly我用自定义验证逻辑创建自己的日期选择器。

我把这个组件放在CellEditingTemplate中。当我按下按钮时,弹出窗口显示,但是在任何地方单击弹出窗口都会导致单元格停止编辑(因为弹出窗口正在从文本框中获取焦点)。我通过添加代码解决了这个问题,如果弹出窗口打开,文本框的焦点可能不会丢失。这对我有用。

此外,在usercontrol的on loaded事件处理程序中,我将焦点放在文本框中。 在你的情况下,它可能是具有焦点的Usercontrol itsefl。

protected override void OnPreviewLostKeyboardFocus(KeyboardFocusChangedEventArgs e) {
             // Don't allow focus to leave the textbox if the popup is open
             if (Popup.IsOpen) e.Handled = true;  
}

private void Root_Loaded(object sender, RoutedEventArgs e) {
       TextBox.Focus();
}

答案 3 :(得分:2)

将弹出窗口中的FocusManager.IsFocusScope附加属性设置为True