我正在使用Silverlight C#和XAML开发Windows Phone应用。我的页面包含一个ListBox,它呈现用户可以操作的数据绑定对象列表,即添加/重命名/删除。
我已经知道项目的添加/重命名是 in-place ,即根据对象的状态(bool IsEditable
交换TextBox的TextBlock (并且使用参数化的VisibilityConverter
来管理相反的可见性状态。
<UserControl.Resources>
<local:VisibilityConverter x:Key="VisibilityConverter" True="Visible" False="Collapsed"/>
<local:VisibilityConverter x:Key="InvertedVisibility" True="Collapsed" False="Visible"/>
</UserControl.Resources>
...
<TextBlock Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource InvertedVisibility}}" />
<TextBox Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource VisibilityConverter}}"/>
问题是我还希望TextBox在可见时自动抓取焦点,这样屏幕上的键盘就会弹出而用户无需点击TextBox。
由于常规TextBox上没有VisibilityChanged事件,我将TextBox子类化为TextBox2并添加了我自己的事件:
public class TextBox2 : TextBox
{
public TextBox2()
{
DefaultStyleKey = typeof(TextBox);
}
public static readonly DependencyProperty VisibilityChangedProperty = DependencyProperty.Register(
"VisibilityChanged",
typeof(string),
typeof(TextBox2),
new PropertyMetadata("Set the VisibilityChanged event handler"));
public event VisibilityChangedEventHandler VisibilityChanged;
public delegate void VisibilityChangedEventHandler(object sender, EventArgs e);
public new Visibility Visibility
{
get
{
return base.Visibility;
}
set
{
if (base.Visibility != value)
{
base.Visibility = value;
VisibilityChanged(this, new EventArgs());
}
}
}
}
现在我的XAML看起来像这样:
<TextBlock Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource InvertedVisibility}}"/>
<local:TextBox2 Text="{Binding Name}" Visibility="{Binding IsEditable, Converter={StaticResource VisibilityConverter}}" VisibilityChanged="ListEdit_VisibilityChanged"/>
事件处理程序如下:
void ListEdit_VisibilityChanged(object sender, EventArgs e)
{
TextBox textBox = (TextBox)sender;
if (textBox.Visibility == System.Windows.Visibility.Collapsed)
return;
textBox.Focus();
}
TextBox2正确渲染,在运行时表现得像TextBox一样,但是当数据绑定翻转IsEditable
的值时,我的VisibilityChanged事件处理程序没有触发。
IsEditable
定义了Visibility,TextBox2确实可见,因此数据绑定正常工作。
我可以通过获取TextBox2实例并在代码中设置其可见性来以编程方式触发事件。这也有效。
但是这个负责设置可见性的数据绑定方案似乎不起作用。
任何想法为什么不呢?
答案 0 :(得分:2)
以下是我使用的2个解决方案。
解决方案1不需要子类,但解决方案2更可重用。
<强> 1 即可。您可以订阅Loaded
的{{1}}事件,并强行关注,如下所示:
TextBox
此解决方案进入递归循环,但您可能需要添加一些检查以使其更安全。
<强> 2 即可。保留子类 void TextBox_Loaded_Focus(object sender, System.Windows.RoutedEventArgs e) {
ForceFocusControl((Control)sender);
}
void ForceFocusControl(Control control) {
control.Focus();
if (FocusManager.GetFocusedElement() != control) {
Dispatcher.BeginInvoke(() => ForceFocusControl(control));
}
}
,而是创建一个绑定到基类的TextBox2
属性的私有MyVisibility
依赖项属性,同时指定DependencyProperty_Changed处理程序,如下所示:
Visibility
答案 1 :(得分:0)
这就是我的TextBox2类现在的样子:
public class TextBox2 : TextBox
{
public event VisibilityChangedEventHandler VisibilityChanged;
public delegate void VisibilityChangedEventHandler(object sender, EventArgs e);
public static readonly DependencyProperty VisibilityChangedProperty = DependencyProperty.Register(
"VisibilityChanged", typeof(VisibilityChangedEventHandler), typeof(TextBox2), null);
static readonly DependencyProperty MirrorVisibilityProperty = DependencyProperty.Register(
"MirrorVisibility", typeof(Visibility), typeof(TextBox2), new PropertyMetadata(MirrorVisibilityChanged));
public TextBox2()
{
SetBinding(TextBox2.MirrorVisibilityProperty, new Binding("Visibility") { Source = this });
}
static void MirrorVisibilityChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
((TextBox2)obj).VisibilityChanged(obj, null); // raise event
}
}