wpf

2011-03-01 68 views
1

转移焦点在控件的子部分(在其模板中)我有一个文本框需要在某些情况下“转换”到DatePicker中。wpf

容易与模板完成:

<TextBox.Style> 
    <Style TargetType="{x:Type TextBox}"> 
     <Style.Triggers> 
      <Trigger Property="local:MyTextBox.IsDate" Value="True"> 
       <Setter Property="Template" Value="{StaticResource DateTextBoxTemplate}" /> 
      </Trigger> 
     </Style.Triggers> 
    </Style> 
</TextBox.Style> 

然后:

<ControlTemplate x:Key="DateTextBoxTemplate" TargetType="TextBox"> 
    <DatePicker x:Name="DateContent" 
       Text="{Binding RelativeSource={RelativeSource AncestorType=TextBox}, Path=Text, Mode=TwoWay}" /> 
</ControlTemplate> 

麻烦的是:重点不是“转移”到了日期选择器,当我点击它。

即:如果我点击控件,datePicker不会获得焦点。我必须再次点击它才会发生这种情况。

我知道我可以在我背后做代码:

protected override void OnGotFocus(RoutedEventArgs e) 
{ 
    base.OnGotFocus(e); 

    if (IsDate) 
    { 
     DatePicker dateContent = Template.FindName("DateContent", this) as DatePicker; 
     if (dateContent != null) dateContent.Focus(); 
    } 
} 

但这并不真正满足我,因为我敢肯定有办法做到这一切的XAML和我只是不了解它。

我发现了另外一个提到FocusManager.FocusedElement="{Binding ElementName=DateContent}"选项的问题,但我不知道我可以在哪里放这段代码:它不能被添加到controlTemplate(正如我怀疑的那样),如果我把它放在一个网格封装在模板中的datePicker,它基本上是无用的。

所以我只能在xaml中做到这一点?如果是,如何?

回答

5

我已经在过去使用这一点,它一直

<ControlTemplate x:Key="DateTextBoxTemplate" TargetType="TextBox"> 
    <DatePicker x:Name="DateContent" Text="{Binding RelativeSource={RelativeSource AncestorType=TextBox}, Path=Text, Mode=TwoWay}"/> 
    <ControlTemplate.Triggers> 
     <Trigger Property="IsFocused" Value="True"> 
      <Setter TargetName="DateContent" 
        Property="FocusManager.FocusedElement" 
        Value="{Binding ElementName=DateContent}" /> 
     </Trigger> 
    </ControlTemplate.Triggers> 
</ControlTemplate> 
+0

谢谢,这是我一直在寻找的东西。这不起作用,但稍微调整了一下,我可以让它按照想要的那样行事:触发器最终看起来像这样:(您可以编辑您的答案以供将来参考) – David 2011-03-01 10:15:41

+0

@大卫:更新我的答案与您的加法 – 2011-03-01 10:23:42

+0

完美,作品一种享受。我想知道为什么需要TargetName =“DateContent”,因为直接在模板对象上设置FocusManager.FocusedElement附加属性的值应该没有什么区别。但我试图将其删除,并打破了行为,所以我认为这是必要的,我无法理解。 – David 2011-03-01 14:16:26

2

,你可以告诉它应该被默认加载的时候集中在DatePicker达到预期的行为。要做到这一点,你可以创建一个Attached Behavior这样的:

public static class FocusExtensions 
{ 
    public static bool GetIsDefaultFocusElement(DependencyObject obj) 
    { 
     return (bool)obj.GetValue(IsDefaultFocusElementProperty); 
    } 

    public static void SetIsDefaultFocusElement(DependencyObject obj, bool value) 
    { 
     obj.SetValue(IsDefaultFocusElementProperty, value); 
    } 

    public static readonly DependencyProperty IsDefaultFocusElementProperty = 
     DependencyProperty.RegisterAttached("IsDefaultFocusElement", typeof(bool), typeof(FocusExtensions), new UIPropertyMetadata(false, OnIsDefaultFocusElementChanged)); 

    private static void OnIsDefaultFocusElementChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
    { 
     var fe = (FrameworkElement)d; 

     if (!(bool)e.NewValue) 
     { 
      return; 
     } 

     if (fe.IsLoaded) 
     { 
      SetFocus(fe); 
     } 
     else 
     { 
      fe.Loaded += OnDefaultFocusElementLoaded; 
     } 
    } 

    private static void OnDefaultFocusElementLoaded(object sender, RoutedEventArgs e) 
    { 
     var fe = (FrameworkElement) sender; 

     fe.Loaded -= OnDefaultFocusElementLoaded; 

     SetFocus(fe); 
    } 

    private static void SetFocus(FrameworkElement element) 
    { 
     element.Focus(); 
    } 
} 

然后你可以设置IsDefaultFocusElement附加属性的DatePicker和每次DatePicker加载它会接收焦点时间:

<ControlTemplate x:Key="DateTextBoxTemplate" TargetType="TextBox"> 
    <DatePicker x:Name="DateContent" 
       Text="{Binding RelativeSource={RelativeSource AncestorType=TextBox}, Path=Text, Mode=TwoWay}" 
       my:FocusExtensions.IsDefaultFocusElement="True" /> 
</ControlTemplate> 

此行为可以在应用程序中的任何其他位置使用,您需要指定默认情况下需要关注的元素(例如,当您打开一个对话框并且希望第一个字段被立即聚焦时)。

+0

嗯,谢谢,但这对我的情况稍微矫枉过正。它确实比OnGotFocus覆盖更好,因为它保留了MVVM模式,但我更喜欢在这种情况下通过meleak更简单的解决方案解释。 – David 2011-03-01 10:10:51

+0

@David - 如果您不打算扩展您的应用程序,并且您确定不需要在任何地方设置默认焦点,那么,是的,提供我的@Meleak的解决方案显然更简单。 – 2011-03-01 10:15:56

+0

是的,这确实是刚才这种情况下,我并不需要过分,所以我会用简单的坚持。但我会记住您的建议以备将来参考,因为它绝对有一些好的想法 – David 2011-03-01 10:18:12