我终于得到了一个 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>

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 的问题。

有帮助吗?

解决方案

使用您的示例代码,它非常适合我。我进行了单个字符更改,然后移动焦点,全名更新正确发生

顺便说一句,您对 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");
            }
        }
    }

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

其他提示

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

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

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

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

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top