[PropertyChanged事件,设置DataContext后为null

问题描述 投票:1回答:2

我正在将View的构造方法中View的DataContext设置为ViewModel的实例,只是标准的东西。此后不久,从View Aggregator正确捕获的Event Aggregator触发了一个UPDATE_RECENT_DOCUMENTS_LIST事件。属性已更改,并且调用了onPropertyChanged方法,但由于PropertyChanged事件为null,因此它失败。

我接下来要做的是对UI进行的操作,该操作引发CREATE_PROJECT事件,并且相同的ViewModel正在接收事件,除了现在,PropertyChanged事件不再为null,并且一切正常。

设置DataContext之后,在注册到PropertyChanged事件之前是否要经过特定的时间?我是否可以等待某个事件来确保PropertyChanged事件不为null?

[而且,在集成Prism并使用非常方便的EventAggregator之后,我没有使用标准.NET事件遇到此问题。

我在View和ViewModel后面显示我的代码,为简洁起见,省略了View XAML。

ToolBarView.xaml.cs:

namespace ToolBarModule
{   

public partial class ToolBarView : UserControl
    {                           
        public ToolBarView(ToolBarViewModel toolBarViewModel)
        {
            InitializeComponent();             
            this.DataContext = toolBarViewModel;                                
        }        
    }
}

ToolBarViewModel.cs

namespace ToolBarModule
{

public class ToolBarViewModel : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;
    private ToolBarCommands baseCommands;
    private IEventAggregator eventAggregator;

    private KickStartEvent kickStartEvent;
    private SubscriptionToken subscriptionToken;

    private ObservableCollection<IDocumentReference> recentDocuments = new ObservableCollection<IDocumentReference>();

    private ActionCommand newTest;
    private ActionCommand openTest;
    private ActionCommand saveTest;        
    private ActionCommand exitApplication;

    public ToolBarViewModel(){}

    public ToolBarViewModel(IEventAggregator eventAggregator)
    {
        this.eventAggregator = eventAggregator;
        baseCommands = new ToolBarCommands(eventAggregator);
        kickStartEvent = eventAggregator.GetEvent<KickStartEvent>();
        subscriptionToken = kickStartEvent.Subscribe(kickStartEventHandler, ThreadOption.UIThread, true, toolBarEventHandlerFilter);            
    }

    public ICommand NewTest
    {
        get
        {
            if (newTest == null)
            {
                newTest = new ActionCommand(baseCommands.NewTestAction);
            }
            return newTest;
        }
    }

    public ICommand OpenTest
    {
        get
        {
            if (openTest == null)
            {
                openTest = new ActionCommand(baseCommands.OpenTestAction);
            }
            return openTest;
        }
    }

    public ICommand SaveTest
    {
        get
        {
            if (saveTest == null)
            {
                saveTest = new ActionCommand(baseCommands.SaveTestAction);
            }
            return saveTest;
        }
    }


    public ICommand ExitApplication
    {
        get
        {
            if (exitApplication == null)
            {
                exitApplication = new ActionCommand(baseCommands.ExitApplicationAction);
            }
            return exitApplication;
        }
    }

    public ObservableCollection<IDocumentReference> RecentDocuments
    {
        get
        {
            return recentDocuments;
        }

        set
        {
            recentDocuments = value;
            onPropertyChanged("RecentDocuments");
        }
    }

    private void onPropertyChanged(string propertyChanged)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this,new PropertyChangedEventArgs(propertyChanged));
        }

    }

    private void kickStartEventHandler(KickStartEventsArgs e)
    {
        switch (e.EventType)
        {
            case KickStartEventsArgs.KickStartEventType.CREATE_PROJECT:
                onPropertyChanged("RecentDocuments");
            break;                


            case KickStartEventsArgs.KickStartEventType.UPDATE_RECENT_DOCUMENTS_LIST:
            RecentDocuments.Clear();

            foreach (IDocumentReference recentDocs in e.KickStartTestList)
            {
                RecentDocuments.Add(recentDocs);
            }
            onPropertyChanged("RecentDocuments");
            break;
        }
    }
}

}

c# wpf prism datacontext propertychanged
2个回答
0
投票

您必须在UserControl中命名XAML,并将其用于绑定。类似于以下代码:

<UserControl x:Name="uc" >
.
.
.
<TextBox Text="{Binding UserName, Mode=TwoWay, ElementName=uc}"/>

uc是您的UserControl的名称,并且在加载UserControl时还要尝试设置DataContext。

希望获得帮助。


0
投票

您还可以尝试在UserControl下设置网格或Element的DataContext。对我来说,它奏效了。

示例(如果使用DependencyProperty,则不起作用:]

后面的代码:

public MyUserControl()
{
     InitializeComponent();
     this.DataContext = new { LabelText = "Hello World!" };
}

XAML

<UserControl x:Class="CoolProject.ViewModel.MyUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">
<Label x:Name="myLabel" Content="{Binding LabelText}"/>

示例2(我的工作代码):

后面的代码:

public MyUserControl()
{
     InitializeComponent();
     this.myGrid.DataContext = new { LabelText = "Hello World!" };
}

XAML

<UserControl x:Class="CoolProject.ViewModel.MyUserControl"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
         xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
         mc:Ignorable="d" 
         d:DesignHeight="450" d:DesignWidth="800">

<Grid x:Name="myGrid">
    <Label x:Name="myLabel" Content="{Binding LabelText}"/>
</Grid>

© www.soinside.com 2019 - 2024. All rights reserved.