Jan Diederich
Jan Diederich

Reputation: 345

UWP XAML: Bindings.Update() doesn't trigger inner items

If I have GridView items with x:Bind bindings, calling Bindings.Update() has no effect. None of the Items bound properties is read again. It's stuck on the values of first initialization.

But Bindings.Update() works flawless with triggering top-level re-reads of Bound properties (like Width="{x:Bind GridWidth}"). I call the Bindings.Update() at the Page resize event.

How can I force Xaml to re-read the items properties? The items list itself hasn't changed (list count/content), only some of the items properties (like Width="{x:Bind ItemWidth}").

Example:

<!-- Working, re-read -->
<Grid Width="{x:Bind GridWidth}">
    <GridView x:Name="barGrid" ItemsSource="{x:Bind projects}" Background="Aqua" Grid.Row="0">
        <GridView.ItemTemplate>
            <DataTemplate x:Name="DoubleBars" x:DataType="local:Project">
                <!-- This isn't re-read !!! !!! !!! -->
                <StackPanel x:Name="projectItemStack" Width="{x:Bind ItemWidth}" Background="Orange">
                    <Grid>
                        <Rectangle x:Name="RedBar" Fill="Red"/>
                        <TextBlock Text="Test0"/>
                    </Grid>
                    <Grid Margin="0, 3, 0, 5">
                        <Rectangle x:Name="GreenBar" Fill="Lime"/>
                        <TextBlock Text="Test1"/>
                    </Grid>
                </StackPanel>
            </DataTemplate>
        </GridView.ItemTemplate>

        <GridView.ItemsPanel>
            <ItemsPanelTemplate/>
        </GridView.ItemsPanel>

    </GridView>
</Grid>

Upvotes: 0

Views: 1427

Answers (1)

Breeze Liu - MSFT
Breeze Liu - MSFT

Reputation: 3808

If you want to implement that property change updates from a bound Object(Project class), you must make the Object(Project class) implement INotifyPropertyChanged Interface and make the Property subscribe the PropertyChanged event, meanwhile, you should also specific that the x:Bind mode to be OneWay or a TwoWay. More details about binding in UWP app, you can learn from Data binding topic.

To clarify it, I create a sample base on your xaml code.

Here is the Project class that implement the INotifyPropertyChanged Interface.

public class Project:INotifyPropertyChanged
{
    private double itemWidth;
    public double ItemWidth
    {
        get
        {
            return itemWidth;
        }
        set
        {
            itemWidth = value;
            OnPropertyChanged("ItemWidth");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

In the xaml, I change your code to add a Button to change the Project's property and set the x:Bind mode to be OneWay, more about the differences, please see BindingMode Enum.

<Grid Width="{x:Bind GridWidth}">
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <GridView x:Name="barGrid" ItemsSource="{x:Bind projects,Mode=OneWay}" Background="Aqua" Grid.Row="0">
        <GridView.ItemTemplate>
            <DataTemplate x:Name="DoubleBars" x:DataType="local:Project">
                <!-- This isn't re-read !!! !!! !!! -->
                <StackPanel x:Name="projectItemStack" Width="{x:Bind ItemWidth,Mode=OneWay}" Background="Orange">
                    <Grid>
                        <Rectangle x:Name="RedBar" Fill="Red"/>
                        <TextBlock Text="Test0"/>
                    </Grid>
                    <Grid Margin="0, 3, 0, 5">
                        <Rectangle x:Name="GreenBar" Fill="Lime"/>
                        <TextBlock Text="Test1"/>
                    </Grid>
                </StackPanel>
            </DataTemplate>
        </GridView.ItemTemplate>

        <GridView.ItemsPanel>
            <ItemsPanelTemplate/>
        </GridView.ItemsPanel>
    </GridView>

    <Button Click="Button_Click" Content="Click me to change the Items width"/>
</Grid>

This is the page.xaml.cs code behind,

public sealed partial class MainPage : Page
{
    public MainPage()
    {
        this.InitializeComponent();
        projects = new ObservableCollection<Project>();
        projects.Add(new Project { ItemWidth = 300 });
        projects.Add(new Project { ItemWidth = 400 });
        projects.Add(new Project { ItemWidth = 500 });
        projects.Add(new Project { ItemWidth = 600 });
        projects.Add(new Project { ItemWidth = 700 });
    }

    ObservableCollection<Project> projects;
    public double GridWidth { get; set; } = 1000;

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        foreach(var item in projects)
        {
            item.ItemWidth += 100;
        }
    }
}

Then you can see the change when you click the Button and change the ItemWidth property.

Upvotes: 2

Related Questions