Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WrapLayout caching incorrect when source collection is changed #6

Open
moon6969 opened this issue May 4, 2021 · 1 comment
Open
Labels
bug Something isn't working

Comments

@moon6969
Copy link

moon6969 commented May 4, 2021

Description
WrapLayout is not updating correctly when source collection is changed.

Consider an ItemsRepeater bound to a changing source collection "CurrentNode.Things".
With <UniformGridLayout /> the ItemsRepeater displays the correct items from "CurrentNode.Things" as CurrentNode changes.

If I change to <WrapLayout />, the number of displayed items updates correctly, but any items from the previous source are displayed instead.

In the example below, the UniformGridLayout is left, and WrapLayout on the right...
WrapLayout

To Reproduce

    public class Thing
    {
        public string? Name { get; set; }
    }

    public class FolderNode
    {
        public ObservableCollection<Thing> Things { get; set; } = new ObservableCollection<Thing>();

        public FolderNode(List<string> Names)
        {
            foreach (string c in Names)
            {
                Things.Add(new Thing { Name = c });
            }
        }
    }
    public class MainWindowViewModel : ViewModelBase
    {
        private FolderNode _currentNode = default!;
        public FolderNode CurrentNode
        {
            get => _currentNode;
            set
            {
                this.RaiseAndSetIfChanged(ref _currentNode, value);
            }
        }

        ObservableCollection<FolderNode> Folders { get; set; } = new ObservableCollection<FolderNode>();

        public ICommand SelectFolderCommand { get; }

        public MainWindowViewModel()
        {
            Folders.Add(new FolderNode(new List<string>()));
            Folders.Add(new FolderNode(new List<string>() { "A", "B" }));
            Folders.Add(new FolderNode(new List<string>() { "D", "E", "F" }));

            CurrentNode = Folders[0];

            SelectFolderCommand = ReactiveCommand.Create<string>(param =>
            {
                CurrentNode = Folders[int.Parse(param)];
            });
        }
    }
  <Grid ColumnDefinitions="Auto,1*,1*">

    <StackPanel Grid.Column="0">
      <Button Command="{Binding Path=SelectFolderCommand}" CommandParameter="0">0</Button>
      <Button Command="{Binding Path=SelectFolderCommand}" CommandParameter="1">2</Button>
      <Button Command="{Binding Path=SelectFolderCommand}" CommandParameter="2">3</Button>
    </StackPanel>

    <ItemsRepeater Grid.Column="1" Items="{Binding Path=CurrentNode.Things}" Background="Bisque">
      <ItemsRepeater.ItemTemplate>
        <DataTemplate>
          <TextBox Text="{Binding Path=Name}" HorizontalAlignment="Left" />
        </DataTemplate>
      </ItemsRepeater.ItemTemplate>
      <ItemsRepeater.Layout>
        <UniformGridLayout />
      </ItemsRepeater.Layout>
    </ItemsRepeater>

    <ItemsRepeater Grid.Column="2" Items="{Binding Path=CurrentNode.Things}" Background="AliceBlue">
      <ItemsRepeater.ItemTemplate>
        <DataTemplate>
          <TextBox Text="{Binding Path=Name}" />
        </DataTemplate>
      </ItemsRepeater.ItemTemplate>
      <ItemsRepeater.Layout>
        <WrapLayout />
      </ItemsRepeater.Layout>
    </ItemsRepeater>

  </Grid>

Expected behavior
WrapLayout should display the correct items from source!

Desktop:

  • OS: Windows 10 Pro
  • Version 2004 (19041.928)
  • Avalonia 0.10.3
@moon6969 moon6969 added the bug Something isn't working label May 4, 2021
@KaddaOK
Copy link

KaddaOK commented Feb 15, 2024

In case anyone else comes across this issue:

<ItemsControl> with a <WrapPanel> doesn't seem to suffer from the same issue as <ItemsRepeater> with a <WrapLayout>.

I'm not sure if you lose anything like virtualization support or what not when you make the switch, but if ItemsRepeater and ItemsControl are interchangeable in your case, just change

    <ItemsRepeater>
      <ItemsRepeater.Layout>
        <WrapLayout />
      </ItemsRepeater.Layout>
    </ItemsRepeater>

to

    <ItemsControl>
      <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
          <WrapPanel />
        </ItemsPanelTemplate>
      </ItemsControl.ItemsPanel>
    </ItemsControl>

and you're good. Or at least, I was, so far. 🤷‍♂️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants