Связывание данных в WPF? - PullRequest
1 голос
/ 20 июня 2011

Я пытаюсь настроить привязку данных в WPF.У меня есть класс person, который обновляется (как в oldschool) через одно текстовое поле, а другое текстовое поле должно отражать изменение объекта person через привязку данных (раньше это было type = 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 Ответ

4 голосов
/ 20 июня 2011

Здесь куча проблем.

Первая и, вероятно, самая важная из них - это то, что вы реализовали Person.name как поле.Привязка не работает с полями.Person.name должно быть свойством.

Следующая проблема, с которой вы столкнулись, заключается в том, что если вы хотите, чтобы элемент управления обновлялся со значением свойства при изменении этого свойства, ваш класс должен реализовать изменение свойствауведомление.(Это еще одна причина, по которой Person.name должно быть свойством.)

Третья проблема заключается в том, что вы используете методы WinForms в приложении WPF.Привязка данных исключает большинство случаев использования для события TextChanged.(Не все: это может быть полезно при разработке пользовательских элементов управления.)

Четвертая проблема заключается в том, что нет необходимости в преобразовании значений, поэтому нет необходимости реализовывать преобразователь значений.

APerson класс, который правильно реализует уведомление об изменении свойства, должен выглядеть примерно так:

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 гораздо больше, чем это, но это должно помочь вам в этомправильный путь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...