我终于得到了一个Silverlight MVVM示例,这样当我更改名字和姓氏文本框的值时,全名会自动更改。
然而,奇怪的是,我的模型继承自 INotifyPropertyChanged仅在我更改 至少2个字符 时通知姓。
之前是否有人在Silverlight / XAML / INotifyPropertyChanged中遇到此问题?会是什么呢? 是否有某个设置指示文本框在将其自身更改为“已更改”之前需要更改多少?
以下是我正在使用的代码的主要部分:
Customer.cs:
using System;
using System.Collections.Generic;
using System.ComponentModel;
namespace TestMvvm345.Model
{
public class Customer : INotifyPropertyChanged
{
public int ID { get; set; }
public int NumberOfContracts { get; set; }
private string firstName;
private string lastName;
public string FirstName
{
get { return firstName; }
set
{
firstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("FullName");
}
}
public string LastName
{
get { return lastName; }
set
{
lastName = value;
RaisePropertyChanged("LastName");
RaisePropertyChanged("FullName");
}
}
public string FullName
{
get { return firstName + " " + lastName; }
}
#region INotify
public event PropertyChangedEventHandler PropertyChanged;
private void RaisePropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
#endregion
}
}
CustomerHeaderView.xaml:
<UserControl x:Class="TestMvvm345.Views.CustomerHeaderView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel HorizontalAlignment="Left">
<ItemsControl ItemsSource="{Binding}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBox x:Name="FirstName"
Text="{Binding Path=FirstName, Mode=TwoWay}"
Width="150"
Margin="3 5 3 5"/>
<TextBox x:Name="LastName"
Text="{Binding Path=LastName, Mode=TwoWay}"
Width="150"
Margin="0 5 3 5"/>
<TextBlock x:Name="FullName"
Text="{Binding Path=FullName, Mode=TwoWay}"
Margin="0 5 3 5"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Grid>
</UserControl>
CustomerViewModel.cs:
using System.ComponentModel;
using System.Collections.ObjectModel;
using TestMvvm345.Model;
namespace TestMvvm345
{
public class CustomerViewModel
{
public ObservableCollection<Customer> Customers { get; set; }
public void LoadCustomers()
{
ObservableCollection<Customer> customers = new ObservableCollection<Customer>();
//this is where you would actually call your service
customers.Add(new Customer { FirstName = "Jim", LastName = "Smith", NumberOfContracts = 23 });
customers.Add(new Customer { FirstName = "Jane", LastName = "Smith", NumberOfContracts = 22 });
customers.Add(new Customer { FirstName = "John", LastName = "Tester", NumberOfContracts = 33 });
customers.Add(new Customer { FirstName = "Robert", LastName = "Smith", NumberOfContracts = 2 });
customers.Add(new Customer { FirstName = "Hank", LastName = "Jobs", NumberOfContracts = 5 });
Customers = customers;
}
}
}
MainPage.xaml.cs中:
void MainPage_Loaded(object sender, RoutedEventArgs e)
{
CustomerViewModel customerViewModel = new CustomerViewModel();
customerViewModel.LoadCustomers();
CustomerHeaderView.DataContext = customerViewModel.Customers;
}
我在WPF中重新制作了这个项目,它运行正常。也许这是一个Silverlight 3问题。
答案 0 :(得分:2)
使用您的示例代码,它非常适合我。我进行单个字符更改然后移动焦点并正确地发生FullName更新
除此之外,您对NotifyPropertyChanged的使用存在缺陷
public string FirstName
{
get { return firstName; }
set
{
firstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("FullName");
}
}
应该是:
public string FirstName
{
get { return firstName; }
set
{
if (firstName != value)
{
firstName = value;
RaisePropertyChanged("FirstName");
RaisePropertyChanged("FullName");
}
}
}
您希望避免导致事件触发,并且在非更改时发生关联的重新绑定。
答案 1 :(得分:0)
我在Silverlight 2中发现了同样的问题。我认为这是一个错误。这是我的错误报告(目前尚未回答):
答案 2 :(得分:-1)
您可能还希望在Binding语句中包含“UpdateSourceTrigger = PropertyChanged”。即
Text="{Binding Path=FirstName,UpdateSourceTrigger=PropertyChanged}"
这将确保在文本框中进行更改时所有值都会更新。