

public AuthScopeFlags ScopeFlags
{
    get
    {
        return AuthScopeFlags.BasicProfile | AuthScopeFlags.Presence | AuthScopeFlags.FriendsList;
    }
}<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="Auto" />
    </Grid.ColumnDefinitions>
    <StackPanel Grid.Column="1">
        <Button Width="100" Height="23" Margin="2" Content="Query friends" Command="{Binding FriendsQuery}" />
        <Button Width="100" Height="23" Margin="2" Content="Subscribe" Command="{Binding FriendsSubscribeUpdates}" />
        <Button Width="100" Height="23" Margin="2" Content="Unsubscribe" Command="{Binding FriendsUnsubscribeUpdates}" />
        <Button Width="100" Height="23" Margin="2" Content="Query status" Command="{Binding PresenceQuery}" CommandParameter="{Binding SelectedFriend}" />
    </StackPanel>
    <ListView x:Name="FriendsListView" Grid.Column="0" Margin="2" ItemsSource="{Binding Friends}" SelectedItem="{Binding SelectedFriend}" SelectionChanged="FriendsListView_SelectionChanged">
        <ListView.View>
            <GridView>
                <GridViewColumn Header="Friend" Width="300" DisplayMemberBinding="{Binding EpicAccountId}">
                    <GridViewColumn.HeaderContainerStyle>
                        <Style TargetType="{x:Type GridViewColumnHeader}">
                            <Setter Property="HorizontalContentAlignment" Value="Left" />
                        </Style>
                    </GridViewColumn.HeaderContainerStyle>
                </GridViewColumn>
                <GridViewColumn Header="Friend Status" Width="150" DisplayMemberBinding="{Binding FriendsStatus}">
                    <GridViewColumn.HeaderContainerStyle>
                        <Style TargetType="{x:Type GridViewColumnHeader}">
                            <Setter Property="HorizontalContentAlignment" Value="Left" />
                        </Style>
                    </GridViewColumn.HeaderContainerStyle>
                </GridViewColumn>
                <GridViewColumn Header="Status" Width="150" DisplayMemberBinding="{Binding Status}">
                    <GridViewColumn.HeaderContainerStyle>
                        <Style TargetType="{x:Type GridViewColumnHeader}">
                            <Setter Property="HorizontalContentAlignment" Value="Left" />
                        </Style>
                    </GridViewColumn.HeaderContainerStyle>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>
public partial class FriendsView : UserControl
{
    public FriendsViewModel ViewModel { get { return ViewModelLocator.Friends; } }
    public FriendsView()
    {
        InitializeComponent();
        DataContext = ViewModel;
    }
    private void FriendsListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
    }
}public class Friend : BindableBase
{
    private EpicAccountId _epicAccountId;
    public EpicAccountId EpicAccountId
    {
        get { return _epicAccountId; }
        set { SetProperty(ref _epicAccountId, value); }
    }
    private FriendsStatus _friendsStatus;
    public FriendsStatus FriendsStatus
    {
        get { return _friendsStatus; }
        set { SetProperty(ref _friendsStatus, value); }
    }
    private Status _status;
    public Status Status
    {
        get { return _status; }
        set { SetProperty(ref _status, value); }
    }
}public class FriendsViewModel : BindableBase
{
    private ObservableCollection<Friend> _friends;
    public ObservableCollection<Friend> Friends
    {
        get { return _friends; }
        set { SetProperty(ref _friends, value); }
    }
    private Friend _selectedFriend;
    public Friend SelectedFriend
    {
        get { return _selectedFriend; }
        set { SetProperty(ref _selectedFriend, value); }
    }
    private ulong _notificationId;
    public ulong NotificationId
    {
        get { return _notificationId; }
        set { SetProperty(ref _notificationId, value); }
    }
}private static FriendsViewModel _friends;
public static FriendsViewModel Friends
{
    get { return _friends ??= new FriendsViewModel(); }
}public static class FriendsService
{
    public static void QueryFriends()
    {
        var queryFriendsOptions = new QueryFriendsOptions()
        {
            LocalUserId = EpicAccountId.FromString(ViewModelLocator.Main.AccountId)
        };
        ViewModelLocator.Main.StatusBarText = $"Querying friends...";
        App.Settings.PlatformInterface.GetFriendsInterface()
.QueryFriends(queryFriendsOptions, null, (QueryFriendsCallbackInfo queryFriendsCallbackInfo) =>
        {
            Debug.WriteLine($"QueryFriends {queryFriendsCallbackInfo.ResultCode}");
            if (queryFriendsCallbackInfo.ResultCode == Result.Success)
            {
                var getFriendsCountOptions = new GetFriendsCountOptions()
                {
                    LocalUserId = EpicAccountId.FromString(ViewModelLocator.Main.AccountId)
                };
                var friendsCount = App.Settings.PlatformInterface.GetFriendsInterface()
.GetFriendsCount(getFriendsCountOptions);
                for (int i = 0; i < friendsCount; i++)
                {
                    var getFriendAtIndexOptions = new GetFriendAtIndexOptions()
                    {
                        LocalUserId = EpicAccountId.FromString(ViewModelLocator.Main.AccountId),
                        Index = i
                    };
                    var friend = App.Settings.PlatformInterface.GetFriendsInterface()
.GetFriendAtIndex(getFriendAtIndexOptions);
                    if (friend != null)
                    {
                        var getStatusOptions = new GetStatusOptions()
                        {
                            LocalUserId = EpicAccountId.FromString(ViewModelLocator.Main.AccountId),
                            TargetUserId = friend
                        };
                        var friendStatus = App.Settings.PlatformInterface.GetFriendsInterface()
.GetStatus(getStatusOptions);
                        ViewModelLocator.Friends.Friends.Add(new Friend()
                        {
                            EpicAccountId = friend,
                            FriendsStatus = friendStatus
                        });
                    }
                }
            }
            ViewModelLocator.Main.StatusBarText = string.Empty;
        });
    }
}public class FriendsQueryCommand : CommandBase
{
    public override bool CanExecute(object parameter)
    {
        return !string.IsNullOrWhiteSpace(ViewModelLocator.Main.AccountId);
    }
    public override void Execute(object parameter)
    {
        ViewModelLocator.Friends.Friends = new ObservableCollection<Friend>();
        FriendsService.QueryFriends();
    }
}public FriendsQueryCommand FriendsQuery { get; set; }
public FriendsViewModel()
{
    FriendsQuery = new FriendsQueryCommand();
}Friends.FriendsQuery.RaiseCanExecuteChanged();<TabItem x:Name="Friends" Header="Friends">
    <views:FriendsView />
</TabItem>

public static void SubscribeUpdates()
{
    var addNotifyFriendsUpdateOptions = new AddNotifyFriendsUpdateOptions();
    ViewModelLocator.Main.StatusBarText = $"Adding notification for friends updates...";
    ViewModelLocator.Friends.NotificationId = App.Settings.PlatformInterface.GetFriendsInterface()
.AddNotifyFriendsUpdate(addNotifyFriendsUpdateOptions, null, (OnFriendsUpdateInfo onFriendsUpdateInfo) =>
    {
        Debug.WriteLine($"OnFriendsUpdate: {onFriendsUpdateInfo.TargetUserId}");
        ViewModelLocator.Friends.Friends.SingleOrDefault(f => f.EpicAccountId == onFriendsUpdateInfo.TargetUserId).FriendsStatus = onFriendsUpdateInfo.CurrentStatus;
    });
    ViewModelLocator.Friends.FriendsSubscribeUpdates
.RaiseCanExecuteChanged();
    ViewModelLocator.Friends.FriendsUnsubscribeUpdates
.RaiseCanExecuteChanged();
    ViewModelLocator.Main.StatusBarText = string.Empty;
}
public static void UnsubscribeUpdates()
{
    ViewModelLocator.Main.StatusBarText = $"Removing notification for friends updates...";
    App.Settings.PlatformInterface.GetFriendsInterface()
.RemoveNotifyFriendsUpdate(ViewModelLocator.Friends.NotificationId);
    ViewModelLocator.Friends.NotificationId = 0;
    ViewModelLocator.Friends.FriendsSubscribeUpdates
.RaiseCanExecuteChanged();
    ViewModelLocator.Friends.FriendsUnsubscribeUpdates
.RaiseCanExecuteChanged();
    ViewModelLocator.Main.StatusBarText = string.Empty;
}ViewModelLocator.Friends.FriendsSubscribeUpdates
.RaiseCanExecuteChanged();
ViewModelLocator.Friends.FriendsUnsubscribeUpdates
.RaiseCanExecuteChanged();[...]
var friendStatus = App.Settings.PlatformInterface.GetFriendsInterface()
.GetStatus(getStatusOptions);
        ViewModelLocator.Friends.Friends.Add(new Friend()
        {
            EpicAccountId = friend,
            FriendsStatus = friendStatus
        });
    }
}ViewModelLocator.Friends.FriendsSubscribeUpdates
.RaiseCanExecuteChanged();
ViewModelLocator.Friends.FriendsUnsubscribeUpdates
.RaiseCanExecuteChanged();public class FriendsSubscribeUpdatesCommand : CommandBase
{
    public override bool CanExecute(object parameter)
    {
        return !string.IsNullOrWhiteSpace(ViewModelLocator.Main.AccountId) && (ViewModelLocator.Friends.Friends.Count != 0) && (ViewModelLocator.Friends.NotificationId == 0);
    }
    public override void Execute(object parameter)
    {
        FriendsService.SubscribeUpdates();
    }
}public class FriendsUnsubscribeUpdatesCommand : CommandBase{
    public override bool CanExecute(object parameter)
    {
        return !string.IsNullOrWhiteSpace(ViewModelLocator.Main.AccountId) && (ViewModelLocator.Friends.Friends.Count != 0) && (ViewModelLocator.Friends.NotificationId != 0);
    }
    public override void Execute(object parameter)
    {
        FriendsService.UnsubscribeUpdates();
    }
}public FriendsQueryCommand FriendsQuery { get; set; }
public FriendsSubscribeUpdatesCommand FriendsSubscribeUpdates { get; set; }
public FriendsUnsubscribeUpdatesCommand FriendsUnsubscribeUpdates { get; set; }
public FriendsViewModel()
{
    FriendsQuery = new FriendsQueryCommand();
    FriendsSubscribeUpdates = new FriendsSubscribeUpdatesCommand();
    FriendsUnsubscribeUpdates = new FriendsUnsubscribeUpdatesCommand();
}public override bool CanExecute(object parameter)
{
    if (parameter == null)
        return !string.IsNullOrWhiteSpace(ViewModelLocator.Main.AccountId);
    else
        return ((Friend)parameter).EpicAccountId != null;
}
public override void Execute(object parameter)
{
    if (parameter == null)
        PresenceService.Copy(EpicAccountId
.FromString(ViewModelLocator.Main.AccountId), EpicAccountId
.FromString(ViewModelLocator.Main.AccountId));
    else
        PresenceService.Query(((Friend)parameter).EpicAccountId);
}public FriendsQueryCommand FriendsQuery { get; set; }
public FriendsSubscribeUpdatesCommand FriendsSubscribeUpdates { get; set; }
public FriendsUnsubscribeUpdatesCommand FriendsUnsubscribeUpdates { get; set; }
public PresenceQueryCommand PresenceQuery { get; set; } 
public FriendsViewModel()
{
    FriendsQuery = new FriendsQueryCommand();
    FriendsSubscribeUpdates = new FriendsSubscribeUpdatesCommand();
    FriendsUnsubscribeUpdates = new FriendsUnsubscribeUpdatesCommand();
    PresenceQuery = new PresenceQueryCommand();
}ViewModel.PresenceQuery.RaiseCanExecuteChanged();