1

我终于得到了一个 Silverlight MVVM 示例,这样当我更改名字和姓氏文本框的值时,全名会自动更改。

然而,奇怪的是,我从 INotifyPropertyChanged 继承的模型只有在我更改名字或姓氏的至少 2 个字符时才会收到通知。

  • 如果我将“Smith”更改为“Smith1”,则不会触发任何事件
  • 如果我将“Smith”更改为“Smith12”,则按预期触发事件

有没有人在 Silverlight/XAML/INotifyPropertyChanged 中遇到过这个问题?会是什么呢?是否有一个设置指示文本框在通知自己“已更改”之前需要更改多少?

以下是我正在使用的代码的主要部分:

客户.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>

客户视图模型.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 的问题。

4

3 回答 3

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

您希望避免在未更改时触发事件以及相关的重新绑定。

于 2009-04-02T11:13:58.350 回答
0

我在 Silverlight 2 中注意到了同样的问题。我认为这是一个错误。这是我的错误报告(目前未答复):

http://silverlight.net/forums/t/59207.aspx

于 2009-06-05T18:53:24.380 回答
-1

您可能还希望在 Binding 语句中包含“UpdateSourceTrigger=PropertyChanged”。IE

Text="{Binding Path=FirstName,UpdateSourceTrigger=PropertyChanged}"

这将确保每次您在文本框中进行更改时都会更新该值。

于 2009-04-02T12:05:37.867 回答