C# ViewModel中的数据未从PageLoad事件绑定到XAML
我不熟悉MVVM体系结构。我正在构建一个UWP应用程序。我基本上有一个视图(XAML)、代码隐藏(XAML.cs)、ViewModel和数据服务 我的视图/XAML如下所示:C# ViewModel中的数据未从PageLoad事件绑定到XAML,c#,mvvm,data-binding,uwp,uwp-xaml,C#,Mvvm,Data Binding,Uwp,Uwp Xaml,我不熟悉MVVM体系结构。我正在构建一个UWP应用程序。我基本上有一个视图(XAML)、代码隐藏(XAML.cs)、ViewModel和数据服务 我的视图/XAML如下所示: <Page x:Class="SnapBilling.SyncModule.SyncView" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="
<Page
x:Class="SnapBilling.SyncModule.SyncView"
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"
xmlns:controls="using:Microsoft.Toolkit.Uwp.UI.Controls"
mc:Ignorable="d" Loaded="Page_Loaded"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<Grid.Resources>
<!--DataTemplate for Published Date column defined in Grid.Resources. PublishDate is a property on the ItemsSource of type DateTime -->
<DataTemplate x:Key="ProgressTemplate" >
<ProgressBar x:Name="progressBar1" Value="{Binding Value.ProgressPercentage}" Maximum="100" Margin="20"/>
</DataTemplate>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="4*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
<controls:DataGrid x:Name="BackupSummaryDataGrid"
Grid.Row="0"
Margin="40"
ItemsSource="{x:Bind DataContext.UploadProgressInfoDict}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AlternatingRowBackground="Transparent"
AreRowDetailsFrozen="False"
AreRowGroupHeadersFrozen="True"
AutoGenerateColumns="False"
CanUserReorderColumns="True"
CanUserResizeColumns="True"
ColumnHeaderHeight="32"
FrozenColumnCount="0"
GridLinesVisibility="None"
HeadersVisibility="Column"
HorizontalScrollBarVisibility="Visible"
IsReadOnly="False"
MaxColumnWidth="400"
RowDetailsVisibilityMode="Collapsed"
RowGroupHeaderPropertyNameAlternative="Range"
SelectionMode="Extended"
VerticalScrollBarVisibility="Visible"
>
<controls:DataGrid.Columns>
<controls:DataGridTextColumn Tag="SyncType" Header="Sync Type" Binding="{Binding Key}" IsReadOnly="True" />
<controls:DataGridTextColumn Tag="remaining" Header="Pending Items" Binding="{Binding Value.remainingNow}" IsReadOnly="True" />
<controls:DataGridTemplateColumn Header="% remaining" CellTemplate="{StaticResource ProgressTemplate}" />
<controls:DataGridTextColumn Header="Status" Binding="{Binding Value.ProgressMessage}" IsReadOnly="True"/>
</controls:DataGrid.Columns>
</controls:DataGrid>
</Grid>
</Page>
如何解决这个问题?因此代码将执行的顺序是
DataContext
时,DataContext
中的绑定不为空,但是当您在加载的页面中设置DataContext
时,DataContext
将为空,因此您在视图中看不到任何数据
如果可以的话,我建议您在绑定之前在构造函数中初始化视图模型。但是,如果出于某种原因,您需要在Page_Loaded
事件中绑定它,您需要一种方法来告诉视图在其更改时更新值
幸运的是,框架已经有了解决方案,您可以在ViewModel上使用INotifyPropertyChanged
界面,这样它就可以通知视图属性值的更改,在您的情况下,我猜是value.ProgressPercentage
但是您必须编写一个事件处理程序,它将相应地更新您的视图
像这样的
private void OnViewModelPropertyChange(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(ViewModel.prop1):
// do something
break;
case nameof(ViewModel.prop2):
// do something else
break;
}
}
这就是我建议您改用数据绑定的原因,这并不是非常复杂,但它会为您节省几行额外的编码。现在在代码背后:
public SyncView()
{
this.Loaded += SyncView_Loaded;
}
private void SyncView_Loaded(object sender, RoutedEventArgs e)
{
this.InitializeComponent();
DataContext = new SyncViewModel(ServiceLocator.Current.GetService<ICommonServices>());
}
原因:之前我创建了一个视图模型对象(例如,VM)并将其保存在codebehind类的属性中,然后用该属性设置datacontext。后来,我将itemssource与该对象的UploadProgressInfoDict类绑定
ItemsSource=“{Binding VM.UploadProgressInfoDict}”
拆下这一块,效果很好 我已经使用了INotifyPropertyChanged。但我想,你的解决方案的前两段对我来说是可行的。显然,datacontext没有在较早时正确设置。
private void OnViewModelPropertyChange(object sender, PropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(ViewModel.prop1):
// do something
break;
case nameof(ViewModel.prop2):
// do something else
break;
}
}
public SyncView()
{
this.Loaded += SyncView_Loaded;
}
private void SyncView_Loaded(object sender, RoutedEventArgs e)
{
this.InitializeComponent();
DataContext = new SyncViewModel(ServiceLocator.Current.GetService<ICommonServices>());
}
ItemsSource="{Binding UploadProgressInfoDict}"