3

我有这样的控件:

<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=>UserControl=>PopupMenu=>TextBox 永远不会获得焦点。

编辑

但是当我在没有 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>
4

2 回答 2

0

尝试这样的事情:

使用用户控件:

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

没有用户控制:

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;
        }      
    }
}
于 2012-07-15T11:18:27.470 回答
0

考虑有多个文本框需要获得焦点——最简单的解决方案是将DataGridCell Focusable属性设置为False,然后 Popup 获得焦点。参考这个答案

于 2017-01-12T11:52:06.653 回答