1

Silverlight C#とXAMLを使用してWindowsPhoneアプリに取り組んでいます。私のページには、ユーザーが操作できるデータバインドされたオブジェクトのリストをレンダリングするListBoxが含まれています。つまり、追加/名前変更/削除です。

アイテムの追加/名前変更がインプレースbool IsEditableで行われるようになりました。つまり、オブジェクト(プロパティ)の状態に応じてTextBlockをTextBoxに交換し、パラメーター化されたものを使用VisibilityConverterして反対のVisibility状態を管理します。

<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と同じように動作しますが、データバインディングがの値を反転させたときにVisibilityChangedイベントハンドラーが起動しませんIsEditable

IsEditable可視性を定義し、TextBox2が正しく表示されるようになるため、データバインディングが機能します。

TextBox2インスタンスを取得し、その可視性をコードで設定することで、プログラムでイベントを発生させることができます。それも機能します。

ただし、可視性の設定を担当するこのデータバインディングシナリオは機能しないようです。

何かアイデアはありませんか?

4

2 に答える 2

2

これが私が使用する2つのソリューションです。

ソリューション1にはサブクラスは必要ありませんが、ソリューション2の方が再利用可能です。

1Loaded次のように、のイベントをサブスクライブしてTextBox、フォーカスを強制することができます。

    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));
        }
    }

ただし、このソリューションは再帰ループに入りますが、安全性を高めるためにいくつかのチェックを追加することをお勧めします。

2。サブクラスを保持し、基本クラスのプロパティにバインドするTextBox2プライベート依存関係プロパティを作成しますが、次のようにDependencyProperty_Changedハンドラーも指定します。MyVisibilityVisibility

    /// <summary>
    /// <see cref="TextBox2"/> will focus itself when it becomes visible.
    /// </summary>
    public sealed class TextBox2 : TextBox {

        public TextBox2() {

            SetBinding(TextBox2.MyVisibilityProperty, new Binding("Visibility") { Source = this });
        }

        static readonly DependencyProperty MyVisibilityProperty = DependencyProperty.Register(
            /* name = */ "MyVisibilityProperty",
            /* property type = */ typeof(Visibility),
            /* owner type = */ typeof(TextBox2),
            /* meta = */ new PropertyMetadata(MyVisibilityProperty_Changed));

        static void MyVisibilityProperty_Changed(DependencyObject d, DependencyPropertyChangedEventArgs e) {

            TextBox2 TextBox2 = (TextBox2)d;

            if (TextBox2.Visibility == Visibility.Visible) {
                TextBox2.Focus();
            }
        }
    }
于 2013-01-12T14:09:09.020 に答える
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
    }
}
于 2013-01-19T12:32:58.063 に答える