UWP Xaml文本块数据绑定 - 即使属性已更新,UI也不会更新
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UWP Xaml文本块数据绑定 - 即使属性已更新,UI也不会更新相关的知识,希望对你有一定的参考价值。
首先是免责声明:我已经阅读了数十篇有数百个答案的帖子,但我还没有找到解决方案。我试图以我能找到的方式解决这个问题,但UI却没有更新。
我正在编写一个UWP应用程序作为个人项目。在这个特定的场景中,我有一个带有指定DataContext的Grid,其中包含一系列绑定到属性的TextBlock。我使用“Binding”而不是“x:Bind”,因为Grid是ControlTemplate的一部分。
- 我用INotifyPropertyChanged实现了属性。
- 我有支持领域。
- 我已经完成了调试,并且更新了属性并保留了分配的值。
- 我尝试过使用UpdateSourceTrigger = PropertyChanged。
- 我尝试过不同的模式 - OneWay / TwoWay等。
问题:UI完全忽略了更改,并且永远不会更新。
我已在页面构造函数中设置了一个值,并且已设置,但此后不会应用任何更改...永远。
请参阅下面的相关代码片段,也许有人可以看到我没有的东西。
提前致谢。
网格XAML:
<Grid
Grid.Row="1"
BorderBrush="{StaticResource SystemControlChromeLowAcrylicElementBrush}"
BorderThickness="2,0,2,2">
<Grid.DataContext>
<views:MenusPage />
</Grid.DataContext>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="auto" />
<ColumnDefinition Width="152" />
<ColumnDefinition Width="152" />
<ColumnDefinition Width="152" />
<ColumnDefinition Width="152" />
<ColumnDefinition Width="152" />
</Grid.ColumnDefinitions>
<TextBlock
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
Padding="15,0,0,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
FontWeight="Bold"
Text="Totals" />
<Border
Grid.Row="0"
Grid.Column="3"
Margin="0,2,0,-2"
BorderBrush="{StaticResource SystemControlChromeLowAcrylicElementBrush}"
BorderThickness="2,0,0,0">
<TextBlock
Padding="10,0,0,0"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding CaloriesTotal, Mode=OneWay}" />
</Border>
<Border
Grid.Row="0"
Grid.Column="4"
Margin="0,2,0,-2"
BorderBrush="{StaticResource SystemControlChromeLowAcrylicElementBrush}"
BorderThickness="2,0,0,0">
<TextBlock
Padding="10,0,0,0"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding ProteinTotal}" />
</Border>
<Border
Grid.Row="0"
Grid.Column="5"
Margin="0,2,0,-2"
BorderBrush="{StaticResource SystemControlChromeLowAcrylicElementBrush}"
BorderThickness="2,0,0,0">
<TextBlock
Padding="10,0,0,0"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding FatTotal}" />
</Border>
<Border
Grid.Row="0"
Grid.Column="6"
Margin="0,2,0,-2"
BorderBrush="{StaticResource SystemControlChromeLowAcrylicElementBrush}"
BorderThickness="2,0,0,0">
<TextBlock
Padding="10,0,0,0"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding CarbTotal}" />
</Border>
<Border
Grid.Row="0"
Grid.Column="7"
Margin="0,2,0,-2"
BorderBrush="{StaticResource SystemControlChromeLowAcrylicElementBrush}"
BorderThickness="2,0,0,0">
<TextBlock
Padding="15,0,0,0"
VerticalAlignment="Center"
FontWeight="Bold"
Text="{Binding SugarTotal}" />
</Border>
</Grid>
属性:
private double _caloriesTotal;
public double CaloriesTotal
{
get { return _caloriesTotal; }
set { Set(ref _caloriesTotal, value); }
}
private double _proteinTotal;
public double ProteinTotal
{
get { return _proteinTotal; }
set { Set(ref _proteinTotal, value); }
}
private double _fatTotal;
public double FatTotal
{
get { return _fatTotal; }
set { Set(ref _fatTotal, value); }
}
private double _carbTotal;
public double CarbTotal
{
get { return _carbTotal; }
set { Set(ref _carbTotal, value); }
}
private double _sugarTotal;
public double SugarTotal
{
get { return _sugarTotal; }
set { Set(ref _sugarTotal, value); }
}
的PropertyChanged:
public event PropertyChangedEventHandler PropertyChanged;
private void Set<T>(ref T storage, T value, [CallerMemberName]string propertyName = null)
{
if (Equals(storage, value))
{
return;
}
storage = value;
OnPropertyChanged(propertyName);
}
private void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
代码设置值:(注意:这是缩短版本,但应用相同的效果,在构造函数中设置值应用值和UI更新,但在页面上的任何其他位置设置值,在任何执行的方法中,它们是忽略,UI显示零。)
CaloriesTotal = 10;
ProteinTotal = 20;
FatTotal = 30;
CarbTotal = 40;
SugarTotal = 50;
请为主对象使用绑定DataContext,而不是DataGrid:
<Window.DataContext>
<views:MenusPage />
</Window.DataContext>
我找到了解决方案,虽然我对它的实际工作方式感到茫然,而其他应该工作的“正常”解决方案却没有,但这已经超出了我的范围。
无论如何,感谢@ jsmyth886和@Alexey的帮助和故障排除建议。
自发布此问题以来,我尝试将属性分离到另一个类,在<Models:MenuTypesModel x:Key="MenuTotals" />
块中引用<Page.Resources>
- 失败
我试着设置DataContext
本身的Page
- 失败了
在我的问题中<Grid> ... </Grid>
XAML是,如上所述,ControlTemplate
的一部分我甚至将块移出控制模板并移到页面本身以消除与其他数据源的任何冲突 - 请注意所有不同的命名结构和路径,所以最终应该没有发生冲突 - 这也不起作用,所以 - 失败了
是@Alexey的回应让我想到了一个不同的路线,我的搜索最终导致我发布了Binding to Self/'this' in XAML这个解决了我的问题的帖子。
我从网格中删除了以下datacontext:
<Grid.DataContext>
<views:MenusPage />
</Grid.DataContext>
并用这个DataContext="{Binding ElementName=_this}"
替换它并确保我的文本块绑定,最终结果(非常短版):
<Grid ... DataContext="{Binding ElementName=_this}">
...
<TextBlock ... Text="{Binding CaloriesTotal}" />
...
</Grid>
最后将一个Name属性添加到Page本身:
x:Name="_this"
它工作!!!!
我没有改变我设置属性的方式。
我的属性仍然按照问题定义,我没有视图模型或其他类,也没有在CodeBehind中设置DataContext。
只需将DataContext="{Binding ElementName=_this}"
the grid和x:Name="_this"
添加到页面,UI就可以每次都反映属性的更改。
一个奇怪的简单解决方案。
注意:虽然,虽然我尝试了不同的东西,但当我在ContentTemplate之外的页面本身上有Grid时,我在codebehind DataContext = this;
中设置了页面的DataContext并且它开始填充但仍然无法影响Grid中的Grid控制模板。
所以,除非有一个我没有看到的冲突,或者因为我有其他不相关的DataSource以及直接分配到需要它的控件......我无法用这个简单的绑定来解释它为什么现在有效。
无论如何,感谢您的帮助,我希望将来可以帮助其他人。
以上是关于UWP Xaml文本块数据绑定 - 即使属性已更新,UI也不会更新的主要内容,如果未能解决你的问题,请参考以下文章
UWP DependencyObject 绑定 Windows.UI.Xaml.Markup.XamlParseException