如何设置标签的目标,以便访问键将重点放在ContentControl内的控件上?

时间:2011-01-27 18:18:26

标签: wpf focus

在WPF中,如何设置标签的目标,以便访问键将焦点设置在 ContentControl 中的控件上?

我正在使用MVVM,所以我不想在后面的代码中添加任何代码来解决这个问题。

我已经尝试将路径设置为“Content”,并且在运行时抛出异常,因为没有转换器用于设置为 ContentControl 内容的数据类型。如果我没有设置路径,则焦点设置为 ContentControl 本身。

<Label Target="{Binding ElementName=_myContentControl, Path=Content}"/>

3 个答案:

答案 0 :(得分:2)

使用GotFocus事件。

<Label Target="myContentControl" >_Content</Label>
<ContentControl x:Name="myContentControl" GotFocus="myContentControl_GotFocus">

private void myContentControl_GotFocus(object sender, RoutedEventArgs e)
{
    var cc = sender as ContentControl;
    if (cc != null && cc.Content is UIElement)
        ((UIElement)cc.Content).Focus();
}    

使用分离的类FocusBehavior的另一种解决方案:

class FocusBehaviour : Behavior<ContentControl>
{
    protected override void OnAttached()
    {
        base.OnAttached();
        this.AssociatedObject.GotFocus += new System.Windows.RoutedEventHandler(AssociatedObject_GotFocus);
    }

    void AssociatedObject_GotFocus(object sender, System.Windows.RoutedEventArgs e)
    {
        var c = this.AssociatedObject.Content as UIElement;
        if (c != null)
            c.Focus();
    }

    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.GotFocus -= new System.Windows.RoutedEventHandler(AssociatedObject_GotFocus);
    }
}

XAML:

<ContentControl x:Name="myContentControl">
    <i:Interaction.Behaviors>
        <local:FocusBehaviour />
    </i:Interaction.Behaviors>
</ContentControl>

这种方式需要一个名为System.Windows.Interactivity的dll,并与Expression Blend SDK一起安装。

答案 1 :(得分:1)

您还可以使用转换器将标签的Target绑定到Content的{​​{1}}:

ContentControl

声明转换器:

[ValueConversion(typeof(ContentControl), typeof(UIElement))]
public class ToContentConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        var source = value as ContentControl;
        if (source == null)
        {
            throw new ArgumentException("ToContentConverter source must be a ContentControl.");
        }

        return source.Content;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

并使用它:

<Converters:ToContentConverter x:Key="ToContentConverter" />

答案 2 :(得分:0)

我采用的方法类似于vorrtex的想法,但不需要添加对System.Windows.Interactivity的引用

使用事件处理程序创建一个布尔附加属性,以便更改它。将此属性添加到xaml中的内容控件。添加属性后,事件处理程序将触发,您可以在此处订阅内容控件上的获取焦点事件。

在获得焦点事件处理程序中,您将焦点移动到将成为内容的下一个对象!请确保在内容控件上设置IsTabStop = False,否则您将无法从内容中移出+ Tab。

public static bool? GetFocusContent(DependencyObject obj)
    {
        return (bool?)obj.GetValue(FocusContentProperty);
    }

    public static void SetFocusContent(DependencyObject obj, bool? value)
    {
        obj.SetValue(FocusContentProperty, value);
    }

    public static readonly DependencyProperty FocusContentProperty =
        DependencyProperty.RegisterAttached("FocusContent", typeof(bool?), typeof(MyClassName),
        new UIPropertyMetadata(OnFocusContentChanged));

    static void OnFocusContentChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        if (((bool?)e.NewValue).Value == true)
        {
            ContentControl cControl = obj as ContentControl;

            if (cControl!= null)
            {
                cControl.GotFocus += OnGotFocus;
            }
        }
    }

    static void OnGotFocus(object sender, RoutedEventArgs e)
    {
        ContentControl cControl = sender as ContentControl;

        // You should check the original source against the sender to make sure that
        // you don't prevent focus from getting to a child of your content.
        if (cControl != null && e.OriginalSource == sender) 
        {
            cControl.MoveFocus(new TraversalRequest(FocusNavigationDirection.Next));
        }
    }