如何防止UserControl将焦点从其父对象中移开?

时间:2014-06-05 01:03:13

标签: c# wpf mvvm user-controls

我正在为我的应用程序使用MVVM,并且有一个允许用户输入基本人员信息的表单。该表单包括一个UserControl,它基本上是一个ItemsControl,包含可以动态创建的textBoxes。这是一个简化版本:

<ItemsControl x:Name="items" ItemsSource="{Binding MyItemsCollection}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <Grid x:Name="row">
                <TextBox x:Name="textBox" Text="{Binding ContactInfo, ValidatesOnExceptions=True}" extensions:FocusExtension.IsFocused="{Binding IsFocused}"/>
            </Grid>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
<Button x:Name="NewItemButton" Command="{Binding AddItemToMyCollectionCommand}" />

我希望刚刚创建的TextBox获得焦点,因此我添加了一个附加属性。这是其中的一部分:

public static readonly DependencyProperty IsFocusedProperty =
        DependencyProperty.RegisterAttached("IsFocused", typeof(bool), typeof(FocusExtension), new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));

private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var uie = (UIElement)d;
    if ((bool)e.NewValue)
    {
        uie.Focus();
    }
}

在包含UserControl的表单中,前后还有其他几个文本框。 UserControl有自己的ViewModel,我通过容器的ViewModel中的属性将其设置为控件的DataContext。基本上,容器的简化版本如下所示:

<StackPanel Orientation="Horizontal" />
    <TextBox x:Name="firstName" />
    <TextBox x:Name="lastName" />
    <local:DynamicFormUserControl
        x:Name="phones"
        DataContext="{Binding PhonesViewModel}" />
    <local:DynamicFormUserControl
        x:Name="emails"
        DataContext="{Binding EmailsViewModel}" />
    <TextBox x:Name="address" />
</StackPanel>

我的问题是我希望firstName TextBox在第一次加载表单时获得焦点,但表单继续将焦点放在手机UserControl的第一个TextBox上。我尝试通过在表单的Loaded事件上使用firstName.Focus()来覆盖它,但是这不起作用,并且无论我尝试了什么,焦点仍然是手机userControl而不是表单中的第一个元素包含它。

有人知道如何解决这个问题吗?

感谢。

2 个答案:

答案 0 :(得分:0)

你去吧

FocusManager.FocusedElement="{Binding ElementName=firstName}"添加到您的堆叠面板

<StackPanel Orientation="Horizontal" 
            FocusManager.FocusedElement="{Binding ElementName=firstName}"/>
    <TextBox x:Name="firstName" />
    <TextBox x:Name="lastName" />
    <local:DynamicFormUserControl
        x:Name="phones"
        DataContext="{Binding PhonesViewModel}" />
    <local:DynamicFormUserControl
        x:Name="emails"
        DataContext="{Binding EmailsViewModel}" />
    <TextBox x:Name="address" />
</StackPanel>

另请注意,您可能需要阻止用户控件中的项控件自行聚焦

<ItemsControl x:Name="items" Focusable="False" >
    <ItemsControl.ItemTemplate>

答案 1 :(得分:0)

我想我设法找到了解决方案。问题是我创建的表单本身就是一个窗口内的用户控件,从来没有得到焦点。我不认为那是相关的,所以我在之前的帖子中没有提到它 - 抱歉。我在this解决方案中找到了强制关注用户控件的解决方案。

基本上,当我在窗口中有一个UserControl时,即使我尝试使用Focus()或FocusedElement设置焦点,它也不会获得焦点。所以为了解决这个问题,我在另一篇文章中找到了一个解决方法。基本上我将它添加到包含firstName TextBox的UserControl的代码隐藏。如果我们调用UserControl,比如说,PersonalInfoUserControl,控件的构造函数将如下所示:

public PersonalInfoUserControl()
{
    InitializeComponent();
this.IsVisibleChanged += new DependencyPropertyChangedEventHandler(UserControl_IsVisibleChanged); 
}

我在控件的IsVisibleChanged事件中添加了一个事件处理程序。该方法如下所示:

void UserControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue == true)
{
        Dispatcher.BeginInvoke(
    DispatcherPriority.ContextIdle,
    new Action(delegate()
    {
    firstName.Focus();
    }));
} 
}