PropertyChanged始终为null

时间:2010-10-09 02:43:57

标签: silverlight-4.0

这是我的MainPage.xaml: -

<UserControl x:Class="SilverlightPlainWCF.MainPage"
    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"
    mc:Ignorable="d"
    d:DesignHeight="450" d:DesignWidth="800" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" xmlns:my="clr-namespace:SilverlightPlainWCF.CustomersServiceRef" Loaded="UserControl_Loaded">
    <UserControl.Resources>
        <CollectionViewSource x:Key="customerViewSource" d:DesignSource="{d:DesignInstance my:Customer, CreateList=True}" />
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White">
        <sdk:DataGrid AutoGenerateColumns="False" Height="426" HorizontalAlignment="Left" ItemsSource="{Binding}" Margin="12,12,0,0" Name="customerDataGrid" RowDetailsVisibilityMode="VisibleWhenSelected" VerticalAlignment="Top" Width="776">
            <sdk:DataGrid.Columns>
                <sdk:DataGridTextColumn x:Name="addressColumn" Binding="{Binding Path=Address}" Header="Address" Width="SizeToHeader" />
                <sdk:DataGridTextColumn x:Name="cityColumn" Binding="{Binding Path=City}" Header="City" Width="SizeToHeader" />
                <sdk:DataGridTextColumn x:Name="companyNameColumn" Binding="{Binding Path=CompanyName}" Header="Company Name" Width="SizeToHeader" />
                <sdk:DataGridTextColumn x:Name="contactNameColumn" Binding="{Binding Path=ContactName}" Header="Contact Name" Width="SizeToHeader" />
                <sdk:DataGridTextColumn x:Name="contactTitleColumn" Binding="{Binding Path=ContactTitle}" Header="Contact Title" Width="SizeToHeader" />
                <sdk:DataGridTextColumn x:Name="countryColumn" Binding="{Binding Path=Country}" Header="Country" Width="SizeToHeader" />
                <sdk:DataGridTextColumn x:Name="customerIDColumn" Binding="{Binding Path=CustomerID}" Header="Customer ID" Width="SizeToHeader" />
                <sdk:DataGridTextColumn x:Name="faxColumn" Binding="{Binding Path=Fax}" Header="Fax" Width="SizeToHeader" />
                <sdk:DataGridTextColumn x:Name="phoneColumn" Binding="{Binding Path=Phone}" Header="Phone" Width="SizeToHeader" />
                <sdk:DataGridTextColumn x:Name="postalCodeColumn" Binding="{Binding Path=PostalCode}" Header="Postal Code" Width="SizeToHeader" />
                <sdk:DataGridTextColumn x:Name="regionColumn" Binding="{Binding Path=Region}" Header="Region" Width="SizeToHeader" />
            </sdk:DataGrid.Columns>
        </sdk:DataGrid>
    </Grid>
</UserControl>

这是我的MainPage.xaml.cs: -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using SilverlightPlainWCF.CustomersServiceRef;
using System.Diagnostics;
using System.Collections.ObjectModel;
using System.ComponentModel;

namespace SilverlightPlainWCF
{
    public partial class MainPage : UserControl, INotifyPropertyChanged
    {
        public MainPage()
        {
            InitializeComponent();
            this.DataContext = Customers;
            this.Loaded += new RoutedEventHandler(MainPage_Loaded);
        }
        public ObservableCollection<Customer> customers;

        public ObservableCollection<Customer> Customers
        {
            get { return customers; }
            set
            {
                customers = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("Customers"));
                }
            }
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {

            CustomersServiceClient objCustomersServiceClient = new CustomersServiceClient();

            objCustomersServiceClient.GetAllCustomersCompleted += (s, res) =>
            {

                if (res.Error == null)
                {
                    Customers = new ObservableCollection<Customer>(res.Result);

                }
                else
                {
                    MessageBox.Show(res.Error.Message);
                }
            };

            objCustomersServiceClient.GetAllCustomersAsync();
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {

            // Do not load your data at design time.
            // if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            // {
            //  //Load your data here and assign the result to the CollectionViewSource.
            //  System.Windows.Data.CollectionViewSource myCollectionViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["Resource Key for CollectionViewSource"];
            //  myCollectionViewSource.Source = your data
            // }
            // Do not load your data at design time.
            // if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
            // {
            //  //Load your data here and assign the result to the CollectionViewSource.
            //  System.Windows.Data.CollectionViewSource myCollectionViewSource = (System.Windows.Data.CollectionViewSource)this.Resources["Resource Key for CollectionViewSource"];
            //  myCollectionViewSource.Source = your data
            // }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}

如果我只是移动线: -

this.DataContext = Customers; 

从构造函数到这里: -

if (res.Error == null)
                {
                    Customers = new ObservableCollection<Customer>(res.Result);
                    this.DataContext = Customers; 
                }

它工作正常,我得到所有数据。可能是什么问题。有人能帮助我吗?

2 个答案:

答案 0 :(得分:2)

当你把它放在构造函数中时它不起作用的原因是那时customers字段中还没有任何值。

只有在触发MainPage_Loaded时才会获得该值,由于XAML中的以下行,这不会发生:

Loaded="UserControl_Loaded"

这将执行UserControl_Loaded而不是MainPage_Loaded。您可以做的是从MainPage_Loaded拨打UserControl_Loaded,这可能不是您打算做的。因此,在这种情况下,您应该将XAML更改为:

Loaded="MainPage_Loaded"

您可以完全删除UserControl_Loaded,因为您不再使用它了。

至于将结果分配给DataGrid,您实际上可以通过将结果直接分配到DataContext而不是通过Customers属性来直接执行。

但如果您坚持将其分配给Customers属性并相应地更新DataGrid,那么下一个最简单的解决方案是在Customers set方法的某处包含以下行:

DataContext = value;

如果你真的,真的坚持DataGrid应该在触发PropertyChanged事件时自行更新,而不需要编码DataContext = Customers行,那么你想要的是数据绑定。通过将DataContext属性绑定到您的Customers属性,DataGrid将在收到PropertyChanged事件时更新。

要在XAML中声明数据绑定,您需要为UserControl标记指定一个名称。然后你将绑定分配给DataContext,就像这一行:

DataContext="{Binding Path=Customers, ElementName=theUserControlName}"

如果我是你,而不是必须实现INotifyPropertyChanged界面,我会改为使用Dependency Properties。将您的示例转换为使用Dependency Property,我会:

public static DependencyProperty CustomersProperty =
    DependencyProperty.Register("Customers", typeof(ObservableCollection<Customer>), typeof(MainPage), null);

public ObservableCollection<Customer> Customers
{
    get { return (ObservableCollection<Customer>) GetValue(CustomersProperty); }
    set { SetValue(CustomersProperty, value); }
}

就是这样,财产变更通知将由框架处理。

答案 1 :(得分:0)

我认为问题是在构造函数中你没有这一行:

Customers = new ObservableCollection<Customer>(res.Result);

在尝试将DataContext设置为该值之前。