UWP Xaml文本块数据绑定 - 即使属性已更新,UI也不会更新

时间:2018-03-02 09:38:02

标签: c# xaml data-binding uwp inotifypropertychanged

首先是免责声明:我已经阅读了数十篇有数百个答案的帖子,但我还没有找到解决方案。我试图以我能找到的方式解决这个问题,但UI不会更新。

我正在编写一个UWP应用程序作为个人项目。在这个特定的场景中,我有一个带有指定DataContext的Grid,其中包含一系列绑定到属性的TextBlock。我使用“Binding”而不是“x:Bind”,因为Grid是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); }
}

的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;

3 个答案:

答案 0 :(得分:0)

请使用绑定DataContext作为主对象,而不是DataGrid:

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

答案 1 :(得分:0)

我找到了解决方案,虽然我对其实际工作方式感到茫然,而另一个正常情况却是如此。应该有效的解决方案没有,超出我的范围。

无论如何,感谢@ 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}"网格和x:Name="_this"添加到页面,即可让UI每次都反映对属性的更改。

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

注意:尽管如此,当我尝试不同的东西时,当我在ContentTemplate之外的页面上有Grid时,我在codebehind DataContext = this;中设置了页面的DataContext,它开始填充但仍然未能影响控制模板中的网格。

所以,除非发生冲突,我没有看到,或者因为我有其他不相关的数据源以及直接分配到需要它的控件...我无法理解为什么它现在可以用这个简单结合。

无论如何,感谢您的帮助,我希望将来可以帮助其他人。

答案 2 :(得分:0)

如果出于性能考虑要从NavigationCacheMode(启用/必需)中受益,则必须在数据上下文更改时更新绑定。

 public MainPage()
 {
      this.InitializeComponent();

      this.DataContextChanged += (s, e) => this.Bindings.Update();
 }
相关问题