Silverlight TextBox VisibilityChanged事件

时间:2013-01-10 08:06:25

标签: silverlight events data-binding textbox visibility

我正在使用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实例并在代码中设置其可见性来以编程方式触发事件。这也有效。

但是这个负责设置可见性的数据绑定方案似乎不起作用。

任何想法为什么不呢?

2 个答案:

答案 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
    }
}