WPF中的DataBinding?

时间:2011-06-20 17:16:55

标签: c# wpf xaml data-binding

我正在尝试在WPF中设置数据绑定。我有一个类人,通过一个文本框更新(类似oldschool),另一个文本框应该通过数据绑定镜像对人对象的更改(它曾经是一个类型= twoway但是扔了一个xamlparseexception)。它不是那样工作,并点击显示person.name的按钮,它显示正确的名称,但文本框不会通过数据绑定更新。这是尝试理解数据绑定的不好方法吗?如果你有一个更好的建议来测试它,我完全可以放弃这个代码而不是这样做。

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

1 个答案:

答案 0 :(得分:4)

这里有很多问题。

第一个也许是最重要的一个是您已将Person.name作为字段实施。绑定不适用于字段。 Person.name需要成为财产。

您遇到的下一个问题是,如果您希望在该属性更改时使用属性值更新控件,则您的类必须实现属性更改通知。 (这是Person.name必须成为财产的另一个原因。)

第三个问题是您在WPF应用程序中使用WinForms技术。数据绑定消除了TextChanged事件的大多数用例。 (并非所有:当您开发自定义控件时,它可能很有用。)

第四个问题是不需要进行值转换,因此无需实现值转换器。

正确实现属性更改通知的Person类应如下所示:

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对象并将任何TextBox个对象的Text属性绑定到其Name属性,那么它们都将是保持同步,例如:

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

WPF数据绑定远不止这些,但这应该让你走上正轨。