web-dev-qa-db-ja.com

WPFのテキストボックステキスト変更イベント

たとえば、WFAに2つのテキストボックスがあるとします。次のコードは機能します。

private void textBox1_TextChanged(object sender, EventArgs e)
    {
        textBox2.Text = textBox1.Text;
    }

そして、私はこれを手に入れました。 2番目のテキストボックスのテキストは、変更すると最初のテキストボックスのテキストと同じになります。 enter image description here

しかし、WPFに関しては、まったく異なる動作になります。私がこれをするとき。

private void textBox_TextChanged(object sender, TextChangedEventArgs e)
    {
        textBox1.Text = textBox.Text;
    }

Ctrl + F5を押してアプリケーションをテストしても、何も起こりません。ログには「Build Succeeded」と何も書かれていません。ここで何が問題になっていますか?

そして、これがXAMLコードです。

    <Window x:Class="TextBoxTest.MainWindow"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.Microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TextBoxTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="212,77,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" TextChanged="textBox_TextChanged"/>
    <TextBox x:Name="textBox1" HorizontalAlignment="Left" Height="23" Margin="212,124,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>

</Grid>
7
Roman

Null参照例外が発生しています。 textBoxコントロールが作成されると、textBox1textChangeイベントがトリガーされ、その時点ではtextBox1は作成されていないため、nullになります。 XAMLでテキストボックスの順序を変更するだけで問題ありません。しかし、これを行うには、Bindingを使用してXAMLで直接行うより良い方法があります。

<TextBox x:Name="textBox" />
<TextBox x:Name="textBox1" Text="{Binding ElementName=textBox, Path=Text}" />

(例をより明確にするために一部の属性を除外しました)他のテキストボックスを更新するタイミングに応じて、バインディングにUpdateSourceTriggerを追加できます。

Text="{Binding ElementName=textBox, Path=Text, UpdateSourceTrigger=PropertyChanged}"
9
ceciliaSHARP

そしてもう1つの非常に根本的な理由は、クリアする必要があり、WPFでは実際の最終的な目標はビューのコードビハインドコーディングが少ないということを理解する必要があるということです。はるかにクリーンな方法で、保守性、テスト容易性、および拡張性のキーを実現します。通常のアプリケーション実装パターンのような昔ながらの方法は好きではありません。そして、あなたはこの概念に反対しています。

mainWindow.xaml.cs内(コードビハインド)[旧式]

private void textBox1_TextChanged(object sender, EventArgs e)
{
    textBox2.Text = textBox1.Text;
}

private void textBox_TextChanged(object sender, TextChangedEventArgs e)
{
    textBox1.Text = textBox.Text;
}

mainWindow.xaml(表示)[古い方法]

<Window x:Class="TextBoxTest.MainWindow"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.Microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TextBoxTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
<Grid>
    <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="212,77,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120" TextChanged="textBox_TextChanged"/>
    <TextBox x:Name="textBox1" HorizontalAlignment="Left" Height="23" Margin="212,124,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="120"/>
</Grid>

現在ceciliaSHARPによって回答され、BDLによって編集されました

mainWindow.xaml.cs内(コードビハインド)[WPF方法]

[Say no no and bye bye to the TextChangedEvent]

mainWindow.xaml(ビュー)内[WPF方法]

<Window x:Class="TextBoxTest.MainWindow"
    xmlns="http://schemas.Microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.Microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.Microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:TextBoxTest"
    mc:Ignorable="d"
    Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBox x:Name="textBox" HorizontalAlignment="Left" Height="23" Margin="212,77,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" />
        <TextBox x:Name="textBox1" HorizontalAlignment="Left" Height="23" Margin="212,124,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding ElementName=textBox, Path=Text}" />
    </Grid>
</Window>

または2番目のオプション(「瞬間的に変化するイベントが発生した」のないWPF MVVM方法)

mainWindow.xaml(ビュー)の上記の部分からわずかに変更されました。

    <TextBox HorizontalAlignment="Left" Height="23" Margin="212,77,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Path=Text, Mode=TwoWay}" />
    <TextBox HorizontalAlignment="Left" Height="23" Margin="212,124,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Path=Text, Mode=TwoWay}" />

新しいモデルコードを追加するSomeModelName.cs

using System.ComponentModel;

public class SomeModelName : INotifyPropertyChanged
{

    private string text;

    public string Text
    {
        set
        {
            if (text != value)
            {
                text = value;
                RaisePropertyChanged("Text");
            }
        }
    }

    // some other properties and methods might go here
    // ...

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

または3番目のオプション(「瞬間的に変化するイベントが発生した」というWPF MVVMの方法)、UpdateSourceTriggerを使用

mainWindow.xaml(ビュー)の上記の部分からわずかに変更されました。

    <TextBox HorizontalAlignment="Left" Height="23" Margin="212,77,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Path=Text, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
    <TextBox HorizontalAlignment="Left" Height="23" Margin="212,124,0,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="120" Text="{Binding Path=Text, Mode=TwoWay}" />

これがあなたと私自身を理解できるものにしてくれることを願っています。独自のテキストボックスの動作を定義するのはすべてあなた次第です...

6
Kong CY