放置在DataGrid.DataGridTemplateColumn中的UserControl中的PopupMenu内的文本框永远不会获得KeboardFocus?

时间:2012-07-15 08:59:18

标签: wpf mvvm user-controls wpf-controls wpfdatagrid

我有这样的控件:

<UserControl x:Class="Pouyansoft.WPF.Controls.Common.CommonDropDownPanel"
        d:DesignHeight="20" d:DesignWidth="20">
  <Grid>
    <ToggleButton x:Name="ShowPopupButton"  Click="buttonShowPopup_Click"/>
    <Popup  MaxHeight="300"
        PlacementTarget="{Binding ElementName=ShowPopupButton}"
        PopupAnimation="Slide"
        AllowsTransparency="True"
        Focusable="True" 
        StaysOpen="False"
      >
        <Grid>
          <TextBox x:Name="TXT"/>
        </Grid>
    </Popup>
  </Grid>
</UserControl>

 private void buttonShowPopup_Click(object sender, RoutedEventArgs e)
 {
    popup.IsOpen = true;
 }

当我将此控件放在DataGridTemplateColumn中时,如下所示:

    <DataGrid  CanUserAddRows="False" Grid.ColumnSpan="4"  AutoGenerateColumns="False"  ItemsSource="{Binding}">
        <DataGrid.Columns>
           <DataGridTemplateColumn  MinWidth="200">
             <DataGridTemplateColumn.CellTemplate>
                 <DataTemplate>
                   <DockPanel LastChildFill="True">
                     <WpfCommonControl:CommonDropDownPanel Width="20" Height="20">
                     </WpfCommonControl:CommonDropDownPanel>
                 </DataTemplate>
               </DataGridTemplateColumn.CellTemplate>
          </DataGridTemplateColumn>
        </DataGrid.Columns>
     </DataGrid>

文本框(TXT)没有得到键盘焦点。我不能动摇,为什么?任何想法?

  

DataGrid.DataGridTemplateColumn =&gt; UserControl =&gt; PopupMenu =&gt; TextBox never   得到关注。

修改

但是当我在没有UserControl的情况下这样做时,它完全有效:

 <DataGrid  CanUserAddRows="False" Grid.ColumnSpan="4"  AutoGenerateColumns="False"  ItemsSource="{Binding}">
        <DataGrid.Columns>
           <DataGridTemplateColumn  MinWidth="200">
             <DataGridTemplateColumn.CellTemplate>
                 <DataTemplate>
                   <DockPanel LastChildFill="True">
                     <ToggleButton x:Name="ShowPopupButton"  Click="buttonShowPopup_Click"/>
                     <Popup  MaxHeight="300"
                        PlacementTarget="{Binding ElementName=ShowPopupButton}"
                        PopupAnimation="Slide"
                        AllowsTransparency="True"
                        Focusable="True" 
                        StaysOpen="False">
                      <Grid>
                           <TextBox x:Name="TXT"/>
                      </Grid>
                     </Popup>
                    </DockPanel>
                 </DataTemplate>
               </DataGridTemplateColumn.CellTemplate>
          </DataGridTemplateColumn>
        </DataGrid.Columns>
     </DataGrid>

2 个答案:

答案 0 :(得分:0)

尝试类似的东西:

使用UserControl:

MainWindow.xaml文件:

<Window x:Class="DataGridAndColumnPopup.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525"
        xmlns:WpfCommonControl="clr-namespace:DataGridAndColumnPopup"
        >
    <Grid>
        <DataGrid Name="dgData" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="ID" Binding="{Binding ID}" />
                <DataGridTemplateColumn x:Name="templateColumn" Header="Message">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <DockPanel LastChildFill="True">                                
                                <WpfCommonControl:CommonDropDownPanel>
                                </WpfCommonControl:CommonDropDownPanel>
                            </DockPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

MainWindow.xaml.cs文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;

namespace DataGridAndColumnPopup
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            List<Foo> _source = new List<Foo>();
            for (int i = 0; i < 10; i++)
            {
                _source.Add(new Foo { ID = i, Message = "message " + i });
            }

            dgData.ItemsSource = _source;
        }                 
    }

    public class Foo
    {
        public int ID { get; set; }
        public string Message { get; set; }
    }

    public static class ElementUtil
    {
        public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
        {
            if (depObj != null)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                    if (child != null && child is T)
                    {
                        return (T)child;
                    }

                    T childItem = FindVisualChild<T>(child);
                    if (childItem != null) return childItem;
                }
            }
            return null;
        }      
    }
}

CommonDropDownPanel.xaml文件:

<UserControl x:Class="DataGridAndColumnPopup.CommonDropDownPanel"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="26" d:DesignWidth="114">
    <Grid>        
        <ToggleButton x:Name="ShowPopupButton" Content="Click to edit...."/>
        <Popup  MaxHeight="300"
                                    PlacementTarget="{Binding ElementName=ShowPopupButton}"
                                    IsOpen="{Binding ElementName=ShowPopupButton, Path=IsChecked}"
                                    PopupAnimation="Slide"
                                    AllowsTransparency="True"
                                    Focusable="True" 
                                    StaysOpen="False" Opened="Popup_Opened">
            <Grid>
                <TextBox x:Name="TXT" Text="{Binding Message}" Focusable="True"/>
            </Grid>
        </Popup>        
    </Grid>
</UserControl>

CommonDropDownPanel.xaml.cs文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;

namespace DataGridAndColumnPopup
{
    /// <summary>
    /// Interaction logic for CommonDropDownPanel.xaml
    /// </summary>
    public partial class CommonDropDownPanel : UserControl
    {
        public CommonDropDownPanel()
        {
            InitializeComponent();
        }

        private void Popup_Opened(object sender, EventArgs e)
        {
            TextBox tb = ElementUtil.FindVisualChild<TextBox>((Grid)((sender as Popup).Child));
            if (tb != null)
            {
                tb.SelectAll();
                tb.Focus();
            }
        }      
    }
}

没有UserControl:

XAML文件:

<Window x:Class="DataGridAndColumnPopup.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <DataGrid Name="dgData" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <DataGridTextColumn Header="ID" Binding="{Binding ID}" />
                <DataGridTemplateColumn x:Name="templateColumn" Header="Message">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <DockPanel LastChildFill="True">
                                <ToggleButton x:Name="ShowPopupButton" Content="Click to edit...."/>
                                <Popup  MaxHeight="300"
                                        PlacementTarget="{Binding ElementName=ShowPopupButton}"
                                        IsOpen="{Binding ElementName=ShowPopupButton, Path=IsChecked}"
                                        PopupAnimation="Slide"
                                        AllowsTransparency="True"
                                        Focusable="True" 
                                        StaysOpen="False" Opened="Popup_Opened">
                                    <Grid>
                                        <TextBox x:Name="TXT" Text="{Binding Message}" Focusable="True"/>
                                    </Grid>
                                </Popup>                        
                            </DockPanel>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

代码隐藏文件:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;

namespace DataGridAndColumnPopup
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            List<Foo> _source = new List<Foo>();
            for (int i = 0; i < 10; i++)
            {
                _source.Add(new Foo { ID = i, Message = "message " + i });
            }

            dgData.ItemsSource = _source;
        }

        private void Popup_Opened(object sender, EventArgs e)
        {
            TextBox tb = ElementUtil.FindVisualChild<TextBox>((Grid)((sender as Popup).Child));
            if (tb != null)
            {
                tb.SelectAll();
                tb.Focus();
            }
        }       
    }

    public class Foo
    {
        public int ID { get; set; }
        public string Message { get; set; }
    }

    public static class ElementUtil
    {
        public static T FindVisualChild<T>(DependencyObject depObj) where T : DependencyObject
        {
            if (depObj != null)
            {
                for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
                {
                    DependencyObject child = VisualTreeHelper.GetChild(depObj, i);
                    if (child != null && child is T)
                    {
                        return (T)child;
                    }

                    T childItem = FindVisualChild<T>(child);
                    if (childItem != null) return childItem;
                }
            }
            return null;
        }      
    }
}

答案 1 :(得分:0)

考虑有多个文本框需要关注 - 最简单的解决方案是将DataGridCell Focusable属性设置为False,Popup获得焦点。请参阅此answer