c# - UWP Xaml Textblock 数据绑定(bind) - 即使更新属性,UI 也不更新

标签 c# xaml data-binding uwp inotifypropertychanged

首先是免责声明:我已经阅读了数十篇帖子和数百个答案,但尚未找到解决方案。我已尝试尽一切可能找到的方法来解决此问题,但 UI 并未更新。

我正在编写一个 UWP 应用作为个人项目。在这个特定的场景中,我有一个带有指定 DataContext 的网格,其中包含一系列绑定(bind)到属性的 TextBlock。我使用“Binding”而不是“x:Bind”,因为网格是 ControlTemplate 的一部分。

  • 我已使用 INotifyPropertyChanged 实现了属性。
  • 我有支持字段。
  • 我已完成调试,属性已更新并保留分配的值。
  • 我尝试过使用 UpdateSourceTrigger=PropertyChanged。
  • 我尝试过不同的模式 - OneWay/TwoWay 等。

问题:用户界面完全忽略更改并且从不更新。

我已经在页面构造函数中设置了属性值,并且已设置,但此后不会应用任何更改......永远。

请参阅下面的相关代码片段,也许有人可以看到我没有看到的东西。

提前致谢。

网格 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); }
}

属性更改:

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;

最佳答案

我找到了解决方案,虽然我对它的实际工作原理感到惊讶,而其他应该有效的“正常”解决方案却没有,但超出了我的范围。

无论如何,感谢@jsmyth886和@Alexey在故障排除方面的帮助和建议。

自从发布这个问题以来,我尝试将属性分离到另一个类中,引用 <Models:MenuTypesModel x:Key="MenuTotals" /> <Page.Resources>内阻止--失败

我尝试设置 DataContext Page的本身--失败

<Grid> ... </Grid>正如所说,我的问题中的 XAML 是 ControlTemplate 的一部分。我什至将 block 从控制模板移到页面本身上,以消除与其他数据源的任何冲突 - 请注意所有不同的命名结构和路径,所以最终不应该发生冲突 - 这也不起作用,所以 -- 失败

@Alexey 的回复让我换了一个角度思考,我的搜索最终让我找到了这篇文章 Binding to Self/'this' in XAML这解决了我的问题。

我从网格中删除了以下数据上下文:

<Grid.DataContext>
    <views:MenusPage />
</Grid.DataContext>

并将其替换为 DataContext="{Binding ElementName=_this}"并确保我的文本 block 绑定(bind),最终结果(非常短的版本):

<Grid ... DataContext="{Binding ElementName=_this}">
    ...
    <TextBlock ... Text="{Binding CaloriesTotal}" />
    ...
</Grid>

最后将 a Name 属性添加到页面本身:

x:Name="_this"

它成功了!!!!

我设置属性的方式没有任何改变。

我的属性仍然按照问题定义,我没有 View 模型或其他类,也没有在代码隐藏中设置 DataContext。

只需添加 DataContext="{Binding ElementName=_this}"网格和x:Name="_this"到页面允许 UI 每次都反射(reflect)属性的更改。

一个奇怪的简单解决方案。

注意:尽管如此,当我尝试不同的事情时,当我在 ContentTemplate 之外的页面本身上有网格时,我在代码隐藏中设置了页面的 DataContext DataContext = this;它开始填充,但仍然无法影响控件模板中的网格。

因此,除非存在我没有看到的冲突,或者因为我有其他不相关的数据源,并且直接分配给需要它的控件...我无法理解为什么它现在可以使用这个简单的绑定(bind)来工作。

无论如何,感谢您的帮助,我希望这对将来的其他人有所帮助。

关于c# - UWP Xaml Textblock 数据绑定(bind) - 即使更新属性,UI 也不更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49066419/

相关文章:

c# - WPF 绑定(bind)到 ElementName 引发 NullReferenceException

wpf - 在 silverlight/WP7 应用程序中使用 MVVM 样式模式

javascript - SAPUI5 为 TreeTable/空行创建 JSON

c# - 具有通用功能的方法的工厂模式

c# - 在 C# 中,字段初始化器和对象初始化器如何交互?

c# - 如何将半透明设置为背景,而不是 wp8 的前景?

wpf - 如何检测 WPF 中完成的数据绑定(bind)

c# - 以 URL 作为根属性的 SerializeObject

c# - .NET 中的标准输入和输出

c# - 从前置摄像头捕获的图像旋转 - Windows Phone 8