Как установить цель метки так, чтобы ключ доступа фокусировался на элементе управления внутри ContentControl? - PullRequest
0 голосов
/ 27 января 2011

Как в WPF установить цель метки, чтобы ключ доступа установил фокус на элементе управления внутри ContentControl ?

Я использую MVVM и поэтомуне хочу добавлять какой-либо код к коду для решения этой проблемы.

Я уже пытался установить путь к «Содержанию», и во время выполнения было сгенерировано исключение, потому что нет преобразователя для типа данных, которыйустанавливается на содержимое ContentControl .Если я не задаю путь, то фокус устанавливается на сам ContentControl .

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

Ответы [ 3 ]

2 голосов
/ 27 января 2011

Использование события 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>

Для этого пути требуется dll, которая называется System.Windows.Interactivity и устанавливается вместе с Expression Blend SDK.

1 голос
/ 29 января 2016

Вы также можете использовать конвертер для привязки Target метки к Content из 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" />

И используйте это:

<Label Content="_Thing:" Target="{Binding ElementName=TheContentControl, Converter={StaticResource ToContentConverter}}" />
<ContentControl Name="TheContentControl" />
0 голосов
/ 03 февраля 2011

Подход, который я использовал, был аналогичен идее vorrtex, но не требует добавления ссылки на System.Windows.Interactivity

. Вы создаете логическое присоединенное свойство с помощью обработчика событий, когда оно изменяется.Добавьте это свойство в свой контент-контроль в xaml.Когда свойство добавляется, запускается обработчик событий, и здесь вы можете подписаться на полученное событие фокуса в вашем элементе управления контентом.

В обработчике полученного события фокуса вы перемещаете фокус на следующий объект, который будет содержимым!Убедитесь, что вы установили IsTabStop = False для элемента управления контентом, иначе вы не сможете Shift + 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));
        }
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...