【发布时间】:2011-07-31 09:50:48
【问题描述】:
我有一个列表框,其中包含作为文本框和按钮 (Add) 的项目模板。每当单击按钮时,都会添加一个项目(文本框)。单击按钮后,我想将焦点放在第一个文本框或最近添加的文本框上。我怎么能在 WPF 中做到这一点。如果可能从 MVVM 以可测试的方式结束
【问题讨论】:
-
你能把相关的xaml代码贴在这里吗?用你的代码很容易弄清楚..
标签: wpf mvvm wpf-controls
我有一个列表框,其中包含作为文本框和按钮 (Add) 的项目模板。每当单击按钮时,都会添加一个项目(文本框)。单击按钮后,我想将焦点放在第一个文本框或最近添加的文本框上。我怎么能在 WPF 中做到这一点。如果可能从 MVVM 以可测试的方式结束
【问题讨论】:
标签: wpf mvvm wpf-controls
我会这样做:
ObservableCollection 与项目。SelectedItem。AddItem。AddItem。ComboBox 的SelectedItem 绑定到VM 的SelectedItem。AddItem 命令中,将项目添加到ObservableCollection 并将其分配给VM 的SelectedItem。要实现最后一点,您可以创建一个附加属性,该属性在 getter 中返回 IsFocused,并在 setter 中调用 Focus。然后,您可以将此属性附加到文本框并将其绑定到项目中的 IsFocused 属性。
【讨论】:
我完全同意丹尼尔的回答,但让我用一些代码来澄清这个想法。
首先让我们定义对“真”值做出反应的附加行为,并为其所有者设置焦点。
public static class FocusBehaviour
{
public static bool GetForceFocus(DependencyObject d)
{
return (bool)d.GetValue(FocusBehaviour.ForceFocusProperty);
}
public static void SetForceFocus(DependencyObject d, bool val)
{
d.SetValue(FocusBehaviour.ForceFocusProperty, val);
}
public static readonly DependencyProperty ForceFocusProperty =
DependencyProperty.RegisterAttached("ForceFocus",
typeof(bool),
typeof(FocusBehaviour),
new FrameworkPropertyMetadata(false,
FrameworkPropertyMetadataOptions.None,
(d, e) =>
{
if((bool)e.NewValue)
{
if (d is UIElement)
{
((UIElement)d).Focus();
}
}
}));
}
然后将此行为添加到我们的 TextBox 中:
<DataTemplate>
<TextBox self:FocusBehaviour.ForceFocus="{Binding IsFocused}"/>
</DataTemplate>
当然,您应该将 IsFocused 属性添加到您的项目类:
public class Item : ObservableObject
{
//...
private bool _isFocused = true;
public bool IsFocused
{
get
{
return this._isFocused;
}
set
{
this._isFocused = value;
this.OnPropertyChanged("IsFocused");
}
}
}
在代码中的某个地方,您应该使用 IsFocused 属性为您的项目进行操作。 例如,当您添加新项目时,您应该为所有项目重置 IsFocused,除了新手。初始化集合时,应该只为第一项设置 IsFocused。
【讨论】:
VisualTreeHelper 向上遍历可视化树,以找到具有 Focusable == true 的第一个父级