xaml-csharp-development-skill-for-avalonia

HTML/CSS Pull-to-Refresh and Live Feed Patterns to Avalonia RefreshContainer

Table of Contents

  1. Scope and APIs
  2. Mapping Table
  3. Pull-to-Refresh Event Contract Mapping
  4. Conversion Example: Mobile Activity Feed
  5. C# Equivalent: Activity Feed with Deferral
  6. AOT/Threading Notes
  7. Troubleshooting

Scope and APIs

Primary APIs:

Reference docs:

Mapping Table

HTML/CSS idiom Avalonia mapping
touch pull-to-refresh gesture RefreshContainer PullDirection + RefreshRequested
refresh spinner state machine RefreshVisualizerState
explicit refresh button/JS call RequestRefresh()
async refresh completion callback GetDeferral() / Complete()

Pull-to-Refresh Event Contract Mapping

HTML/JS baseline:

<section class="feed" id="feed"></section>
<button id="refresh">Refresh</button>
.feed {
  overflow-y: auto;
  min-height: 60vh;
}
const feed = document.getElementById("feed");
const refresh = document.getElementById("refresh");

async function reloadFeed() {
  // fetch latest feed
}

refresh?.addEventListener("click", async () => {
  await reloadFeed();
});

Avalonia pattern:

<RefreshContainer PullDirection="TopToBottom"
                  RefreshRequested="OnFeedRefreshRequested">
  <ScrollViewer>
    <ItemsControl ItemsSource="{CompiledBinding FeedItems}" />
  </ScrollViewer>
</RefreshContainer>

Conversion Example: Mobile Activity Feed

<section class="activity-feed">
  <article class="item">Build #102 completed</article>
  <article class="item">Deployment started</article>
  <article class="item">Smoke tests passed</article>
</section>
.activity-feed {
  display: grid;
  gap: .5rem;
}
.activity-feed .item {
  border: 1px solid #2a3348;
  border-radius: .5rem;
  padding: .6rem .75rem;
}
<RefreshContainer PullDirection="TopToBottom"
                  RefreshRequested="OnFeedRefreshRequested">
  <ScrollViewer>
    <ItemsControl ItemsSource="{CompiledBinding FeedItems}">
      <ItemsControl.ItemTemplate>
        <DataTemplate>
          <Border BorderBrush="#2A3348"
                  BorderThickness="1"
                  CornerRadius="8"
                  Padding="10,8"
                  Margin="0,0,0,8">
            <TextBlock Text="{Binding}" />
          </Border>
        </DataTemplate>
      </ItemsControl.ItemTemplate>
    </ItemsControl>
  </ScrollViewer>
</RefreshContainer>

C# Equivalent: Activity Feed with Deferral

using System;
using System.Threading.Tasks;
using Avalonia.Controls;

var feedItems = new[]
{
    "Build #102 completed",
    "Deployment started",
    "Smoke tests passed"
};

var itemsControl = new ItemsControl { ItemsSource = feedItems };

var refreshContainer = new RefreshContainer
{
    PullDirection = PullDirection.TopToBottom,
    Content = new ScrollViewer { Content = itemsControl }
};

refreshContainer.RefreshRequested += async (_, e) =>
{
    var deferral = e.GetDeferral();
    try
    {
        await Task.Delay(250);
        // Reload feed items from service and update bound collection.
    }
    finally
    {
        deferral.Complete();
    }
};

// Programmatic equivalent of a "Refresh" button in web UI.
refreshContainer.RequestRefresh();

AOT/Threading Notes

Troubleshooting

  1. Pull gesture never triggers refresh.
    • Ensure content is scrollable and RefreshContainer wraps the scrolling surface.
  2. Indicator remains active forever.
    • Confirm GetDeferral() result is always completed.
  3. Programmatic refresh does nothing.
    • Verify the control is attached to visual tree and has a refresh handler.