たとえば、WFAに2つのテキストボックスがあるとします。次のコードは機能します。
private void textBox1_TextChanged(object sender, EventArgs e)
{
textBox2.Text = textBox1.Text;
}
そして、私はこれを手に入れました。 2番目のテキストボックスのテキストは、変更すると最初のテキストボックスのテキストと同じになります。
しかし、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>
Null参照例外が発生しています。 textBox
コントロールが作成されると、textBox1
でtextChange
イベントがトリガーされ、その時点では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}"
そしてもう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}" />
これがあなたと私自身を理解できるものにしてくれることを願っています。独自のテキストボックスの動作を定義するのはすべてあなた次第です...