这里有几个“ WPF数据绑定未更新”问题,我已经通读了所有这些问题,包括排名最高的一个: WPF DataBinding not updating?
但是,在这种情况下,我要交换整个对象,更糟糕的是,当我尝试创建自己正在做的事情的可复制版本时,它可以在该版本中工作:
<Window x:Class="WpfApp2.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:WpfApp2"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<StackPanel>
<Label Content="Contact Address" />
<TextBox x:Name="txtContactAddress" Text="{Binding Path=Contact.Address, Mode=OneWay}" />
<Label Content="Organization Address" />
<TextBox x:Name="txtOrgAddress" Text="{Binding Path=Organization.Address, Mode=OneWay}" />
<Button Content="Next Contact" Click="Button_Click" />
</StackPanel>
</Window>
隐藏代码:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace WpfApp2
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public RecordWrapper CurrentRecord;
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
CurrentRecord = new RecordWrapper(new ContactData());
this.DataContext = CurrentRecord;
}
}
public class RecordWrapper : INotifyPropertyChanged
{
private ContactData _Contact;
public ContactData Contact
{
get { return _Contact; }
set
{
_Contact = value;
OnPropertyChanged("Contact");
Organization = _Contact.Organization;
}
}
private OrganizationData _Organization;
public OrganizationData Organization
{
get { return _Organization; }
set
{
_Organization = value;
OnPropertyChanged("Organization");
}
}
public RecordWrapper(ContactData contactData)
{
Contact = contactData;
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string name)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}
#endregion
}
public class ContactData
{
public string Address { get; set; }
public OrganizationData Organization { get; set; }
public ContactData()
{
Address = new Random().Next(1000, 9999) + " Contact Street";
Organization = new OrganizationData();
}
}
public class OrganizationData
{
public string Address { get; set; }
public OrganizationData()
{
Address = new Random().Next(1000, 9999) + " Org Street";
}
}
}
因此,此特定示例按预期方式工作-当我单击“下一个联系人”按钮时,它将生成一个新的RecordWrapper对象,其中包含一个新的ContactData和新的OrganizationData对象,然后将该新对象分配给DataContext,然后我看到文本框会正确更新。
由于我要替换DataContext中的整个对象,因此我什至可以放弃属性通知,并将RecordWrapper减小为:
public class RecordWrapper
{
public ContactData Contact { get; set; }
public OrganizationData Organization { get; set; }
public RecordWrapper(ContactData contactData)
{
Contact = contactData;
Organization = Contact.Organization;
}
}
...而且效果仍然很好。
但是,我的真实代码反映了第一个示例。
在实际代码中,似乎无法使用新对象更新this.DataContext。什么都没有更新,但是也没有错误。在XAML中设置路径也不起作用。实际上,使它起作用的唯一方法是使用代码隐藏直接将绑定设置为数据对象:
BindingOperations.SetBinding(txtContactAddress, TextBox.TextProperty, new Binding() { Source = this.RecordWrapper, Path = new PropertyPath("Contact.Address"), Mode = BindingMode.OneWay });
当我这样做时,我可以看到它正在工作,但是如果我每次必须在每个字段上运行代码以更新绑定,那显然是缺少绑定点。
我很困惑,因为除了具有更多字段,不同的字段名称以及与数据或绑定无关的差异之外,实际代码与示例几乎相同。当我单击一个按钮时,这是确切的代码:
this.Data = new DataBindings(CurrentContact.FetchFake());
this.DataContext = this.Data;
FetchFake()方法生成带有一些虚假数据的新CurrentContact对象,并且我已经验证了第一行运行之后,填充了this.Data.CurrentContact.Login,并且是CurrentContact对象的只读属性(不是字段)。
...和一个XAML文本框如下所示:
<TextBox x:Name="txtAccountNumber" Grid.Column="1" Grid.Row="1" Width="Auto" Text="{Binding Path=CurrentContact.Login, Mode=OneWay}"/>
结果为空白。我还尝试了顺序上的变化(例如,首先将DataContext设置为this.Data,然后设置this.Data.CurrentContact属性,让属性已更改的通知启动,但仍然没有运气。但是如果我运行:
BindingOperations.SetBinding(tabAccount.txtAccountNumber, TextBox.TextProperty, new Binding() { Source = this.Data, Path = new PropertyPath("CurrentContact.Login"), Mode = BindingMode.OneWay });
...然后我将看到该值。
基于这些症状,以及我的第一个示例有效但实际代码无效的事实,有人能想到我应该寻找罪魁祸首的任何地方吗?
答案 0 :(得分:0)
U。弄清楚了。我那里有一段非常古老的代码,它更改了Window和Textbox之间的容器元素的DataContext,从而中断了正确的绑定。我以为我删除了所有内容,但没有删除。正如Erno de Weerd所建议的那样,它DID引发了错误,但是该错误在某些启动日志记录中丢失了。我们可以关闭这个。