在WPF中,如何设置标签的目标,以便访问键将焦点设置在 ContentControl 中的控件上?
我正在使用MVVM,所以我不想在后面的代码中添加任何代码来解决这个问题。
我已经尝试将路径设置为“Content”,并且在运行时抛出异常,因为没有转换器用于设置为 ContentControl 内容的数据类型。如果我没有设置路径,则焦点设置为 ContentControl 本身。
<Label Target="{Binding ElementName=_myContentControl, Path=Content}"/>
答案 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));
}
}