2011-06-20 19 views
1

私はWPFでデータバインディングを設定しようとしています。私は1人のテキストボックスを通して更新された(oldschoolのような)クラスpersonを持っていて、もう1つのtextboxはデータバインディングを通してpersonオブジェクトへの変更をミラーリングすることになっています(これはtype = twowayでしたが、 xamlparseexception)。そのように動作せず、person.nameを示すボタンを押すと正しい名前が表示されますが、テキストボックスはデータバインディングを介して更新されません。これはデータバインディングを理解しようとする悪い方法ですか?もしあなたがそれをテストするためのよりよい提案をしたら、私はこのコードを省略し、代わりにそれを行うだけで大丈夫です。WPFでのデータバインディング?

<Window x:Class="WpfApplication2.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:local="clr-namespace:WpfApplication2" 
    Title="MainWindow" Height="350" Width="525"> 
<Window.Resources> 
    <local:PeoplePleaser x:Key="PeoplePleaser" /> 
</Window.Resources> 
<Grid> 
    <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="12,12,0,0" Name="button1" VerticalAlignment="Top" Width="75" Click="button1_Click" /> 
    <TextBox Height="125" HorizontalAlignment="Left" Margin="81,122,0,0" Name="textBox1" VerticalAlignment="Top" Width="388" FontSize="36" Text="{Binding Converter={StaticResource PeoplePleaser}, Mode=OneWay}" /> 
    <TextBox Height="23" HorizontalAlignment="Left" Margin="209,39,0,0" Name="textBox2" VerticalAlignment="Top" Width="120" TextChanged="textBox2_TextChanged" /> 
</Grid> 

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
      InitializeComponent(); 
    } 

    public static Person myPerson = new Person(); 
    private void button1_Click(object sender, RoutedEventArgs e) 
    { 
     MessageBox.Show(myPerson.name); 
    } 

    private void textBox2_TextChanged(object sender, TextChangedEventArgs e) 
    { 
     myPerson = new Person(textBox2.Text); 
    } 
} 

public class Person 
{ 
    public String name; 

    public Person() 
    { 
     new Person("Blarg"); 
    } 

    public Person(String args) 
    { 
     if (!args.Equals(null)) 
     { 
      this.name = args; 
     } 
     else new Person(); 
    } 

    public Person(String args, Person argTwo) 
    { 
     argTwo = new Person(args); 
    } 
} 

public class PeoplePleaser : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     try 
     { 
      return MainWindow.myPerson.name; 
     } 
     catch (Exception e) 
     { 
      return "meh"; 
     } 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     if (!value.Equals(null)) 
     { 
      return new Person(value.ToString(), MainWindow.myPerson); 
     } 

     else 
     { 
     return(new Person("", MainWindow.myPerson)); 
     } 
    } 
} 

答えて

4

ここでの問題の束があります。

最初に、おそらく最も重要なのは、Person.nameをフィールドとして実装したことです。フィールドとのバインドは機能しません。 Person.nameはプロパティである必要があります。

次の問題は、そのプロパティが変更されたときにプロパティの値でコントロールを更新する場合、クラスがプロパティ変更通知を実装する必要があることです。 (これはPerson.nameがプロパティでなければならない別の理由です)

第3の問題は、WPFアプリケーションでWinForms技術を使用していることです。データバインディングは、TextChangedイベントのほとんどの使用例を排除します。 (すべてではなく、カスタムコントロールを開発するときに便利です)

第4の問題は、値の変換の必要がないため、値コンバータを実装する必要がないことです。あなたがこれを実行したら、あなたがPersonオブジェクトを作成し、そのに任意のTextBoxオブジェクトのTextプロパティをバインドする場合、

public class Person : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    private void OnPropertyChanged(string propertyName) 
    { 
     PropertyChangedEventHandler h = PropertyChanged; 
     if (h != null) 
     { 
     h(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 

    public Person() { } 

    public Person(string name) 
    { 
     Name = name; 
    } 

    private string _Name = "I was created by the parameterless constructor"; 

    public string Name 
    { 
     get { return _Name; } 
     set 
     { 
     if (_Name == value) 
     { 
      return; 
     } 
     _Name = value; 
     OnPropertyChanged("Name"); 
     } 
    } 
} 

:正しくプロパティ変更通知を実装

Personクラスは次のようになります。 Nameプロパティ、それらは全て、同期して維持されます。例:ありこれよりもバインディングWPFデータには、はるかだが、

<StackPanel> 
    <StackPanel.DataContext> 
     <local:Person Name="John Smith"/> 
    </StackPanel.DataContext> 
    <TextBox Text="{Binding Name, Mode=TwoWay}"/> 
    <TextBox Text="{Binding Name, Mode=TwoWay}"/> 
</StackPanel> 

この笙uldは正しい道を進む。

+3

[関連する概要](http://msdn.microsoft.com/en-us/library/ms752347.aspx)にリンクする間違いがあると、間違いないと思います。 –

+0

両方のおかげで! – humanstory

関連する問題