主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ
書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。
2015/11/19
先日、Twitter を眺めてたら、こんな記事が流れてきました。
iOS の UITableView や UICollectionView で表示するデータが無い時の画面を簡単に作る方法
少し前に、自分の作成している 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 のやつみたいにいろいろはできませんが、単純なものならこんな感じでいいかなと。