【问题标题】:DataBinding in WPF?WPF中的数据绑定?
【发布时间】:2020-07-20 00:06:50
【问题描述】:

我正在尝试在 WPF 中设置数据绑定。我有类人,它通过一个文本框更新(类似于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));
        }
    }
}

【问题讨论】:

    标签: c# wpf xaml data-binding


    【解决方案1】:

    这里有一堆问题。

    第一个可能也是最重要的一个是您已将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 数据绑定的功能远不止于此,但这应该会让您走上正确的道路。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-01-10
    • 1970-01-01
    • 1970-01-01
    • 2017-08-20
    • 2011-03-24
    • 2011-03-18
    相关资源
    最近更新 更多