Windows Phone 7 Back button and application Tombstone? - windows-phone-7

In my application i had done this to map my uri in app.xaml.cs, now the thing is if my application deactivates my application exits on MainPage.xaml rather than Eula.xaml. Else the app exits on the same page on which it starts.
In App.xaml
<UriMapper:UriMapper x:Name="mapper">
<UriMapper:UriMapping Uri="/MainPageOrEULA.xaml"/>
</UriMapper:UriMapper>
and in App.xaml.cs
// Get the UriMapper from the app.xaml resources, and assign it to the root frame
UriMapper mapper = Resources["mapper"] as UriMapper;
RootFrame.UriMapper = mapper;
// Update the mapper as appropriate
IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForApplication();
if (isoStorage.FileExists("DataBase/MyPhoneNumber.txt"))
{
mapper.UriMappings[0].MappedUri = new Uri("/MainPage.xaml", UriKind.Relative);
}
else
{
mapper.UriMappings[0].MappedUri = new Uri("/EULA.xaml", UriKind.Relative);
}
Please guide me for the same.
Regards,
Panache.

I suggest that rather than having a whole separate page (which interrupts navigation as you've noticed), just put a grid or usercontrol containing the EULA on the front page that isn't visible. When the user first opens the page, you show the grid/usercontrol, but on subsequent runs, you don't.
<Grid x:Name="LayoutRoot">
<Grid Name="EULA" Visibility="Collapsed" >
<TextBlock Text = "You agree ...." />
<Button Grid.Row="1" Content="I Agree" Click="AgreeClick" />
</Grid>
<Grid Name="MainGrid" >
....
Then in your code behind you can add your test to the loaded event
private void MainPageLoaded()
{
IsolatedStorageFile isoStorage = IsolatedStorageFile.GetUserStoreForApplication();
if (!isoStorage.FileExists("DataBase/MyPhoneNumber.txt"))
{
EULA.Visibility = Visibility.Visible;
MainGrid.Visibility = Visibility.Collapsed;
}
}
Then when the "I agree" button is clicked you can store the file and show the main grid
private void AgreeClick(....)
{
// Create isolated storage file
....
// Hide eula control
EULA.Visibility = Visibility.Collapsed;
MainGrid.Visibility = Visibility.Visible;
}

Related

I tried to update a label in Xamarin.Forms, and it broke the entire app

I have a label on my app's main page that is supposed to update every fifteen seconds, but it only updates once and after that, a lot of things stop working. For example, if I try to open a new page after the label updates, the page's title is drawn in the same place as the back button (both of which are generated in the toolbar by Xamarin), and the page's content doesn't load at all. Also, I have a ListView on the page and if I try to select an item (which is supposed to open a new page) it only works the first time, after which point the ListView disappears, but the orange box that appears behind a selected item stays there.
How the label works at the moment is I have a timer in the App class that chooses a random piece of text from a list that I load in the app's OnStart() function (that part works properly) and then fires an event that is supposed to update the label.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Timers;
using System.Reflection;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using Partylist.Views;
using Partylist.Models;
namespace Partylist
{
public partial class App : Application, INotifyPropertyChanged
{
// Variable to store the currently selected event.
public static Event selectedEvent;
// Variable to store the currently selected list.
public static PartylistList selectedList;
// Struct to store information about tips.
public struct Tip
{
// A short version of the tip for the banner at the bottom of the screen.
public string Summary { get; set; }
// The full tip, which you can read by clicking the "More" button in the banner.
public string Full { get; set; }
}
// Array of tips.
public List<Tip> tips = new List<Tip>();
// Current tip.
public Tip CurrentTip { get; set; }
// Timer that gets the tip to update.
public Timer tipTimer = new Timer(15000);
// Random number generator for choosing the tip.
public Random rand = new Random();
// Event that tells the tip banners on the pages to update.
public static event EventHandler TipUpdate;
// Constructor.
public App()
{
// Do whatever initialization stuff this does.
InitializeComponent();
// Subscribes the timer's event handling function to its event.
tipTimer.Elapsed += OnTimerElapsed;
// Open the first page: the list of events.
MainPage = new NavigationPage(new EventsPage()) {
BarTextColor = Color.FromHex("FF4081")
};
}
// Loads tips data.
private void LoadTips()
{
// Variable for the assembly.
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
// Variable for the stream I use to read the text file.
Stream tipsStream = assembly.GetManifestResourceStream("Partylist.Resources.tips.txt");
// And a variable for the StreamReader.
StreamReader tipsReader = new StreamReader(tipsStream);
// Read the whole file into the list of tips.
while (!tipsReader.EndOfStream)
{
// Read a line into a "sumamry" variable.
string sum = tipsReader.ReadLine();
// Read another line into a "full" variable.
string full = tipsReader.ReadLine();
// Add an item to the list of tips that uses "summary" as the summary
// and "full" as the full tip.
tips.Add(new Tip()
{
Summary = sum,
Full = full
});
}
// Random index of the chosen tip.
int index = rand.Next(tips.Count);
// Set the current tip as the tip at that index.
CurrentTip = tips.ElementAt(index);
// Start timer (if it needs it).
tipTimer.Start();
}
// Event handling function for when the timer goes off.
private void OnTimerElapsed(object source, ElapsedEventArgs e)
{
// Random index of the chosen tip.
int index = rand.Next(tips.Count);
// Set the current tip as the tip at that index.
CurrentTip = tips.ElementAt(index);
// Fire the event to update the pages' tip banners.
TipUpdate?.Invoke(this, e);
}
// Standard lifecycle events.
protected override void OnStart()
{
// Call a function that loads the tips.
LoadTips();
}
protected override void OnSleep()
{
}
protected override void OnResume()
{
}
}
}
In the page's OnAppearing() method, I have the label's text set to the current tip (which at this point is null) and I subscribe the function that updates it to the event that the timer fires.
using Partylist.Models;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace Partylist.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class EventsPage : ContentPage
{
// Text of the tip banner.
public string BannerText { get; set; }
// List of events, used to populate
// the page's ListView (see the XAML).
public ObservableCollection<Event> EventList { get; set; }
// Constructor.
public EventsPage()
{
// Does all the stuff to make the page
// exist that doesn't involve anything
// specific to this particular page in
// this particular app.
InitializeComponent();
// Set the label's BindingContext to the
// App class so it can update its text.
tipLabel.BindingContext = (App)App.Current;
}
// Runs when the page appears.
protected override void OnAppearing()
{
// Call the regular OnAppearing method.
base.OnAppearing();
// Set the BindingContext of the page to itself.
BindingContext = this;
// Update the ListView.
UpdateListView();
// Set the banner's text to the current tip's sumamry.
tipLabel.Text = ((App)App.Current).CurrentTip.Summary;
OnPropertyChanged("CurrentTip");
// Subscribe the OnTipUpdate function to the tipUpdate event in the app
// class.
App.TipUpdate += OnTipUpdate;
}
// Function to update the ListView whent he page loads or when something changes.
private void UpdateListView()
{
// Set the EventList to a new ObservableCollection
// which will be populated.
EventList = new ObservableCollection<Event>();
// Loop to populate the ObservableCollection.
for (int i = 0; i < Directory.GetDirectories(
Environment.GetFolderPath(
Environment.SpecialFolder
.LocalApplicationData))
.Length; i++)
{
// Add a new event.
EventList.Add(new Event()
{
// Set the folder name to the name of the folder
// that the even corresponds to.
FolderName = new DirectoryInfo(Directory.GetDirectories(
Environment.GetFolderPath(
Environment.SpecialFolder
.LocalApplicationData))[i]).Name,
// Sets the date/time created to the folder's
// creation date.
DateCreated = Directory
.GetCreationTime(Directory.GetDirectories(
Environment.GetFolderPath(
Environment.SpecialFolder
.LocalApplicationData))[i]),
// Sets the date/time last edited to the
// folder's write date.
DateEdited = Directory
.GetLastWriteTime(Directory.GetDirectories(
Environment.GetFolderPath(
Environment.SpecialFolder
.LocalApplicationData))[i])
});
// Set the ItemsSource of the ListView in the
// XAML to the ObservableCollection.
EventsListView.ItemsSource = EventList;
// Calls OnPropertyChanged() which makes the ListView update.
OnPropertyChanged("EventList");
}
}
// Function to go to the "New Event" page.
async void OnNewEventClicked(object sender, EventArgs e)
{
await Navigation.PushAsync(new NewEventPage());
}
// Function for when a ListView item is selected.
async void OnItemSelected(object sender, SelectedItemChangedEventArgs e)
{
App.selectedEvent = (Event)e.SelectedItem;
await Navigation.PushAsync(new ListsPage());
}
// Function to delete an event if the "Delete" context action is selected.
async void OnDelete(object sender, EventArgs e)
{
// Represents the thing to be deleted.
var del = (MenuItem)sender;
// Displays a confirmnation popup and stores the user's answer in a variable.
var answer = await DisplayAlert("Delete this event?",
"Are you sure you want to delete the event: \"" +
((Event)del.CommandParameter).FolderName + "\"?", "Delete", "Cancel");
// If the user accepted, delete the event with the MenuItem that ran this function.
if (answer)
{
Directory.Delete(Path.Combine(Environment.GetFolderPath(
Environment.SpecialFolder.LocalApplicationData),
((Event)del.CommandParameter).FolderName), true);
// Set the ItemsSource to null and back to make the ListView update.
EventsListView.ItemsSource = null;
UpdateListView();
}
}
// Function for when the current tip updates.
public void OnTipUpdate(object sender, EventArgs e)
{
// Make the label's text update.
tipLabel.Text = ((App)App.Current).CurrentTip.Summary;
OnPropertyChanged("CurrentTip");
}
}
}
Also, here is the page's XAML in case something is wrong with that.
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
x:Class="Partylist.Views.EventsPage"
Title="Events"
BackgroundColor="White">
<ContentPage.ToolbarItems>
<ToolbarItem IconImageSource="settings_gear.png"
Priority="0"/>
</ContentPage.ToolbarItems>
<ContentPage.Content>
<!--Main layout of the page-->
<StackLayout>
<!--ListView of the events-->
<ListView x:Name="EventsListView"
ItemSelected="OnItemSelected">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<!--These contewxt actions are buttons that appear
when you long press the item (Android) or swipe
left (iOS).-->
<ViewCell.ContextActions>
<MenuItem Clicked="OnDelete"
CommandParameter="{Binding .}"
Text="Delete"
IsDestructive="true"/>
</ViewCell.ContextActions>
<!--This is the content that actually appears-->
<StackLayout Padding="20,5">
<Label Text="{Binding FolderName}"
TextColor="#FF7700"
FontSize="Large"/>
</StackLayout>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<!--"New Event" button-->
<Button Text="+ Add New Event"
TextColor="#ff418b"
FontSize="Large"
BackgroundColor="#00ffffff"
Clicked="OnNewEventClicked"/>
<!--The banner at the bottom of the screen that gives tips-->
<Frame BorderColor="#ff418b"
Padding="0">
<FlexLayout Direction="Row"
AlignItems="Stretch"
JustifyContent="SpaceBetween">
<!--The "Tip" icon-->
<Image Source="tip_icon.png"
Margin="10"
FlexLayout.Basis="50"/>
<!--The short version of the tip-->
<Label x:Name="tipLabel"
VerticalTextAlignment="Center"
TextColor="#bb0099"
FontSize="Medium"
FontAttributes="Bold"
FlexLayout.Basis="250"/>
<!--The button that opens up a screen
with tyhe rest of the tip-->
<Button Text="More"
TextColor="White"
FontAttributes="Bold"
FontSize="Medium"
BackgroundColor="#ff418b"
FlexLayout.Basis="100"/>
</FlexLayout>
</Frame>
</StackLayout>
</ContentPage.Content>
</ContentPage>
What am I doing wrong and how do I keep my app from breaking when the label updates?
You need to update the text in Main thread:
Device.BeginInvokeOnMainThread (() => {
label.Text = "Async operation completed";
});
Refer: xamarin.forms.device.begininvokeonmainthread

Windows phone app, how to use narrator read page title automatically?

I'm developing windows universal app(XAML,C#) on phone, and am enabling accessibility for Narrator. Does anybody know how to get narrator automatically to read page title when a page is opened?
I tried setting automationproperties.name in page but didn't work:
<Page
x:Class="xxxxxx"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
AutomationProperties.Name="Page title to be read"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
The features of the Narrator for UWP are applied when you select a control in a list, or editing a textbox. If you want to read content when the app is opened you should use the SpeechSynthesizer API, which is really easy to implement:
1.- In XAML add a Media Element
<MediaElement x:Name="MediaElement"/>
2.-Then in the code behind of the page:
public MainPage()
{
this.InitializeComponent();
this.Loaded += MainPage_Loaded;
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
ReadTitle();
}
private async void ReadTitle()
{
var voice = SpeechSynthesizer.AllVoices.First();
SpeechSynthesizer reader = new SpeechSynthesizer() { Voice = voice };
var text= this.GetValue(AutomationProperties.NameProperty) as String;
await reader.SynthesizeTextToStreamAsync(text);
MediaElement.SetSource(stream, stream.ContentType);
MediaElement.Play();
}
You can read everything you want passing the string to the reader.
You need to make view-able by narrator. I don't believe you can declare the Name property within the Page Class. Try something like this within the content of your Page:
<HyperlinkButton
NavigateUri="www.bing.com"
AutomationProperties.AutomationID="bing url" //Not Required to work
AutomationProperties.Name="Go to the Bing Homepage"//Narrator will read this
<StackPanel>
<TextBlock Text="Bing Dot Com" />
<TextBlock Text="www.bing.com" />
<StackPanel>
</HyperlinkButton>
https://msdn.microsoft.com/en-us/library/windows/apps/windows.ui.xaml.automation.peers.accessibilityview
EDIT: You may also need to programmatically set focus on the item for this to work

pass data from viewmodel to code behind windows phone

I was trying to use the MVVM pattern on my first (very simple) WP7 app but I got seriously stuck and now I am just trying to get it working without caring about MVVM.
I have a MainViewModel for my MainPage, which works fine. I have a button that passes some data and navigates to a "details page." I had setup a navigation service to navigate to the details page and pass parameters, which works fine. I just couldn't get the databinding to the view working. Since it is a simple app, I decided I would pass the data from the DetailsPageVieModel.cs to the DetailsPage.xaml.cs code behind and do the work there. Here is what that veiw model portion looks like.
public override void Initialize(IDictionary<string, string> parameters)
{
DetailsPage dp = new DetailsPage();
//DetailsPage dp = Application.Current.RootVisual as DetailsPage;
base.Initialize(parameters);
parameters.TryGetValue("url", out vidUrl);
dp.LoadVideoData(vidUrl);
}
In my DetailsPage.xaml.cs I have the following:
public void LoadVideoData(string url)
{
HtmlWeb doc = new HtmlWeb();
doc.LoadAsync("http://mydomain.com/video.php?url=" + url);
doc.LoadCompleted += doc_LoadCompleted;
}
private void doc_LoadCompleted(object sender, HtmlDocumentLoadCompleted e)
{
this.vidTitle.Text = e.Document.GetElementbyId("title").InnerText;
vidId = e.Document.GetElementbyId("youtubeId").InnerText;
this.vidUrl.Source = new Uri("http://mydomain.com/video.php?url=" + vidUrl, UriKind.Absolute);
BitmapImage bi = new BitmapImage();
using (IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile("temp.jpg", FileMode.Open, FileAccess.Read))
{
bi.SetSource(fileStream);
this.vidImg.Height = bi.PixelHeight;
this.vidImg.Width = bi.PixelWidth;
}
}
this.vidImg.Source = bi;
}
And here is the relevant DetailsPage.xaml code
<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<StackPanel>
<TextBlock x:Name="vidTitle" Canvas.ZIndex="99" />
<TextBlock Canvas.ZIndex="99" Text="Tap on the image to view the video." FontSize="14" Margin="0"/>
<Button Margin="0 -50" Padding="0" BorderThickness="0">
<Image x:Name="vidImg" Height="225" />
</Button>
<StackPanel Canvas.ZIndex="99" Height="516">
<phone:WebBrowser x:Name="vidUrl" IsScriptEnabled="True" Height="516" Margin="0"/>
</StackPanel>
</StackPanel>
</Grid>
I am guessing the problem lies with the following
DetailsPage dp = new DetailsPage();
//DetailsPage dp = Application.Current.RootVisual as DetailsPage;
Neither of these lines of code works. The first line executes properly but the page doesn't get updated with the proper data. And the second line gives me a runtime error message when it gets to the dp.LoadVideoData(vidUrl); line.
This is my first Windows Phone app and I would appreciate any help anyone can provide.
Kamal
After digging around some more, I found the following solution.
DetailsPage currentPage = (App.Current as App).RootFrame.Content as DetailsPage;
I put this code in DetailsPageViewModel.cs. But for other newbies like me, there is nothing special about the name of the file. It could have very well been Monkey.cs. The above code just gives you access to the code behind of the current page being displayed.

How are databound views rendered?

When a Windows Phone 7 application opens a view, a certain order of business is followed in order to create. As far as constructors and events go, I have found this order to be true:
Constructor
OnNavigatedTo
OnLoaded
However, I am in a position where I need to databind a List to a ListBox after the basic view (background, other elements etc) has loaded. So I need to know when and how to know that the view is loaded before I get on with the data binding.
I have tried to do this on the OnLoaded-event, but it seems like if I do the data binding here - and right after it traverse those elements - they don't seem to exist yet (the VisualTreeHelper-class can't seem to find the nodes). So as you see, I am stuck.
Any help would be greatly appreciated.
Edit: As requested, here is some more information about what's going on.
My List is populated by some custom (not too complicated) objects, including an asynchronously loaded image (courtesy of delay.LowProfileImageLoader) and a rectangle.
The XAML:
<ListBox x:Name="ChannelsListBox" ItemsSource="{Binding AllChannels}">
//...
<ListBox.ItemTemplate>
<DataTemplate>
<Grid x:Name="ChannelTile" Margin="6,6,6,6" Tap="ChannelTile_Tap" Opacity="0.4">
<!-- context menu goes here -->
<Rectangle Width="136" Height="136" Fill="{StaticResource LightGrayColor}" />
<Image Width="136" Height="136" delay:LowProfileImageLoader.UriSource="{Binding ImageUri}" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
The code-behind:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
base.OnNavigatedTo(e);
UpdateApplicationBar();
pickChannelsViewModel = new PickChannelsViewModel();
DataContext = pickChannelsViewModel;
if (hasUpdatedTiles)
{
pickChannelsViewModel.IsLoading = false; // Set by UpdateTiles()
}
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
// This is where I would data bind the list (instead of in XAML)
UpdateTiles(); // Traverses the list and changes opacity of "selected" items.
}
protected void UpdateTiles()
{
foreach (var item in ChannelsListBox.Items)
{
if (pickChannelsViewModel.SelectedChannels.Contains(item as Channel))
{
var index = ChannelsListBox.Items.IndexOf(item);
// This returns null when databinding in codebehind,
// but not in XAML
ListBoxItem currentItem = ChannelsListBox.ItemContainerGenerator.ContainerFromIndex(index) as ListBoxItem;
if (currentItem != null && VisualTreeHelper.GetChildrenCount(currentItem) == 1)
{
var OuterWrapper = VisualTreeHelper.GetChild(currentItem, 0);
var MiddleWrapper = VisualTreeHelper.GetChild(OuterWrapper, 0);
var InnerWrapper = VisualTreeHelper.GetChild(MiddleWrapper, 0);
Grid currentItemGrid = VisualTreeHelper.GetChild(InnerWrapper, 0) as Grid;
currentItemGrid.Opacity = 1.0;
}
}
}
pickChannelsViewModel.IsLoading = false;
hasUpdatedTiles = true;
}
The items themselves are in-memory (fetched from REST at an earlier stage in the application), so should be available instantaneously.
The issue I am trying to resolve is a fairly long load time on this particularly view (there is about 140 of these items being created, then filtered through and changing the opacity).
I believe you are doing something like:
myListBox.ItemSource=myList;
Once you set the ItemSource of a ListBox the changes in your List should be reflected in the ListBox at all times. If the ListBox is empty the reason must be that the List is not being populated properly or invalid Bindings in the ItemTemplate. You should debug and find out if your List has any items by inserting a breakpoint in the Loaded() method. Also, you've not mentioned what items does your List contains or, where is it being populated in the application? Incomplete information doesn't help anyone.

How to swap images based on the current theme WP7

I've failed certification because I have an image that's all white. So when a user switches to the light theme it fails because you can't see it. How do I swap this imaged based on the theme applied?
Thank you in advance
Question Making an image control invert its colors depending on theme has a simple XAML only answer:
<Image HorizontalAlignment="Center"Stretch="None" Visibility="{StaticResource PhoneLightThemeVisibility}" Source="/MyApplication;component/imageDarkTheme.png" />
<Image HorizontalAlignment="Center" Stretch="None" Visibility="{StaticResource PhoneDarkThemeVisibility}"Source="/MyApplication;component/imageLightTheme.png" />
In XAML
<Image Source="{Binding ImageSource}" />
In the view model that contains property ImageSource
public string ImageSource
{
get
{
if( (Visibility)App.Current.Resources["PhoneDarkThemeVisibility"]
== Visibility.Visible ) {
return "/path/to/dark/image.png";
} else {
return "/path/to/light/image.png";
}
}
private set {}
}
This may not change the picture if the user tombstones your app, changes the theme and switches back to the app.
One way to handle that scenario is to cache the current theme setting in the App class constructor, then compare it with the current setting within App.Application_Activated, if they're different you'll need to somehow indicate that the above view model needs to fire a property changed notification for ImageSource.
For anyone following my comments above - I had to switch from ImageBrush to Image directly (xaml below)
<Button Tag="{Binding}" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="-10,20,0,0" BorderThickness="0" Width="105" Height="102" Click="ShowKioskOnMap_Click">
<Image Source="../images/arrow.png" Width="55" Height="53" ImageOpened="Image_ImageOpened"/>
</Button>
Next in the consructor of the page I'm using --I did the theme lookup to prevent any issues when the app state is restored from taking a phone call for instance (or just loading up the view for the first time)
InitializeComponent();
theme = ""; //field level var (could make it dark by default if needed)
if ((Visibility)App.Current.Resources["PhoneDarkThemeVisibility"] == Visibility.Visible)
{
theme = "dark";
}
else
{
theme = "light";
}
And I had to implement the following in my open event to switch based on theme
private void Image_ImageOpened(object sender, RoutedEventArgs e)
{
var brush = (sender as Image);
if (brush.Stretch == Stretch.Uniform)
{
if (theme == "light")
brush.Source = new BitmapImage(new Uri("../images/arrowLight.png", UriKind.Relative));
brush.Stretch = Stretch.Fill;
}
}

Resources