AppNap settings page
The setting page for AppNap is a rather modified version of button list the main page: instead of clicking an entry to activate it, you click on an entry to be able to edit it. I think the politest thing I can say about my editing interface is that it's functional! I chose to implement the list as a ListBox this time, with the selected state having a template which includes edit controls: the unselected state has the following data template:
<DataTemplate x:Key="TemplateSearchShortcut">
<Border Margin="5" Width="450">
<TextBlock Text="{Binding Name}" Margin="2" TextAlignment="Center" HorizontalAlignment="Stretch"
FontSize="{StaticResource PhoneFontSizeLarge}" />
</Border>
</DataTemplate>
and the selected state:
<DataTemplate x:Key="TemplateSearchShortcutEditable">
<Border Margin="5" Width="444" BorderThickness="2" BorderBrush="{StaticResource PhoneAccentBrush}">
<StackPanel Margin="2">
<TextBlock Text="Name:" Foreground="{StaticResource PhoneForegroundBrush}" Margin="2" />
<TextBox x:Name="TextName" Text="{Binding Name, Mode=TwoWay}" FontSize="{StaticResource PhoneFontSizeMedium}" />
<TextBlock Text="Extra query component:" Foreground="{StaticResource PhoneForegroundBrush}" Margin="2" />
<TextBox Text="{Binding Extra, Mode=TwoWay}" FontSize="{StaticResource PhoneFontSizeMedium}" />
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
<c4fcontrols:RoundButton ImageSource="Images/appbar.up.png" Click="UpButton_Click" />
<c4fcontrols:RoundButton ImageSource="Images/appbar.down.png" Click="DownButton_Click" />
<c4fcontrols:RoundButton ImageSource="Images/appbar.delete.png" Click="DeleteButton_Click" />
</StackPanel>
</StackPanel>
</Border>
</DataTemplate>
I've grabbed some buttons from the Coding4Fun toolkit to save me the effort of styling such things myself! The button actions are fairly obvious: reorder the list, or delete the current item; the item contents are represented as TextBoxes so that the user can edit them - data binding takes care of updating the items. As an example, here's the code dealing with reordering the list:
private void UpButton_Click(object sender, RoutedEventArgs e)
{
MoveCurrentItem(-1);
}
private void DownButton_Click(object sender, RoutedEventArgs e)
{
MoveCurrentItem(1);
}
private void MoveCurrentItem(int delta)
{
var index = this.ListSearch.SelectedIndex;
var settings = ((App)Application.Current).Settings; // Could as easily use ListSearch.ItemsSource
var newIndex = index + delta;
if (newIndex >= 0 && newIndex < settings.Shortcuts.Count)
{
var item = settings.Shortcuts[index];
settings.Shortcuts.RemoveAt(index);
settings.Shortcuts.Insert(newIndex, item);
}
}
On navigating away from the page, I save the new ordering so that it will be picked up next time the application is run - I do it immediately rather than waiting for a suspend event, partly because I use less time when suspending (a trivial amount less in this case) and partly to make sure the state is preserved should the application crash.
The list box item style selects the appropriate template for the item being shown (I'm showing just the template selection below, the actual code also includes some other changes too as well as other state groups:
<Style x:Key="SearchSettingsListBoxItemStyle" TargetType="ListBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="LayoutRoot" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="SelectionStates">
<VisualState x:Name="Unselected" />
<VisualState x:Name="Selected">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="ContentTemplate" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TemplateSearchShortcutEditable}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="SelectedUnfocused">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="ContentTemplate" Storyboard.TargetName="ContentContainer">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource TemplateSearchShortcutEditable}"/>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentControl x:Name="ContentContainer" ContentTemplate="{StaticResource TemplateSearchShortcut}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Margin="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And that's it.