先日、Twitter を眺めてたら、こんな記事が流れてきました。
少し前に、自分の作成している SNS クライアントでも同様のものを実装していたので、
軽く実装方法をメモっておきます。
もしかしたら、これよりもいい方法が在るかもしれません。
ListView に対して、 ItemsSource が空の場合に、任意のコントロールを表示します。
Reactive Extensions を使用していますので、 NuGet から入れておきます。
まずは Behavior を追加します。
UWP 標準だと Behavior`T は存在しないので、WinRTXamlToolKit などを参照しておいてください。
public class EmptyItemsBehavior : Behavior<ListView> { public static readonly DependencyProperty TargetProperty = DependencyProperty.Register( nameof (Target), typeof (string), typeof (EmptyItemsBehavior), new PropertyMetadata(string.Empty)); private int _count; private IDisposable _disposable; public string Target { get { return (string)GetValue(TargetProperty); } set { SetValue(TargetProperty, value); } } public EmptyListBehavior() { this._count = 0; } protected override void OnLoaded() { base.OnLoaded(); var source = this.AssociatedObject.ItemsSource as INotifyCollectionChanged; if (source != null) { this._disposable = source.ToObservable().Subscribe(w => { switch (w.EventArgs.Action) { case NotifyCollectionChangedAction.Add: this._count += w.EventArgs.NewItems.Count; break; case NotifyCollectionChangedAction.Remove: this._count -= w.EventArgs.OldItems.Count; break; case NotifyCollectionChangedAction.Replace: case NotifyCollectionChangedAction.Move: break; case NotifyCollectionChangedAction.Reset: this._count = 0; break; } this.Action(); }); } } protected override void OnUnloaded() { this._disposable.Dispose(); base.OnUnloaded(); } private void Action() { var frameworkElement = (FrameworkElement)((FrameworkElement)this.AssociatedObject.Parent).FindName(this.Target); if (frameworkElement != null) { if (this._count > 0) { this.Visibility = Visibility.Visible; frameworkElement.Visibility = Visibility.Collapsed; } else { this.Visibility = Visibility.Collapsed; frameworkElement.Visibility = Visibility.Visible; } } } }
多少無理矢理感が否めませんが、次は XAML の方です。
<UserControl x:Class="Test.TestPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:behaviors="using:Test.Behaviors" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:i="using:WinRTXamlToolkit.Interactivity"> <Grid> <TextBlock x:Name="NoItemsMessage" Text="No Tweets" /> <ListView ItemsSource="{Binding Items}"> <i:Interaction.Behaviors> <behaviors:EmptyItemsBehavior Target="NoItemsMessage" /> </i:Interaction.Behaviors> <ListView.ItemTemplate> <DataTemplate> <!-- いろいろ --> </DataTemplate> </ListView.ItemTemplate> </ListView> </Grid> </UserControl>
こうしておけば、 ItemsSource
が空の場合は、 No Tweets
というメッセージが表示されます。
コントロールを直接 Binding 出来るような気がしますが、眠いのでこのままにしておきます。
先に貼った iOS のやつみたいにいろいろはできませんが、単純なものならこんな感じでいいかなと。