我在View的构造函数中将我的View的DataContext设置为我的ViewModel实例,只是标准的东西。此后不久, UPDATE_RECENT_DOCUMENTS_LIST 事件从我的ViewModel正确捕获的事件聚合器触发。更改属性并调用onPropertyChanged方法,但由于PropertyChanged事件为null,它会失败。
我接下来要做的是对UI进行操作,引发 CREATE_PROJECT 事件并且相同的ViewModel正在接收事件,除了现在,PropertyChanged事件不再为null并且一切都按预期工作
在将DataContext注册到PropertyChanged事件之前设置DataContext后是否需要经过特定的时间?是否有可以等待的事件确保PropertyChanged事件不为空?
此外,在使用标准的.NET事件之后,我没有遇到这个问题,只是在集成Prism并使用非常方便的EventAggregator之后。
我在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;
}
}
}
}
答案 0 :(得分:1)
您也可以尝试在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>
答案 1 :(得分:0)
您必须在UserControl
中为XAML
命名并在绑定中使用它。类似于以下代码:
<UserControl x:Name="uc" >
.
.
.
<TextBox Text="{Binding UserName, Mode=TwoWay, ElementName=uc}"/>
其中uc
是UserControl
的名称,并且还在加载UserControl时尝试设置DataContext。
希望得到这个帮助。