Статьи

31 день Windows 8 | День № 5: Настройки Контракта


Эта статья является 5-м днем ​​в серии под названием «
31 день Windows 8» . Каждая из статей этой серии будет опубликована как для
HTML5 / JS, так и для
XAML / C # . Вы можете найти дополнительные ресурсы, загрузки и исходный код на нашем
сайте .

31 день Windows 8

day5-амулеты сторонаСегодня мы начинаем серию постов, посвященных контрактам, начиная с настроек приложения. Вероятность того, что они есть в вашем приложении, высока, и вы знаете, что ненавидите иметь с ними дело. Настройки приложения — это только часть чего-то большего в Windows 8, называемая контрактами. Давайте начнем наш разговор о настройках с определения контрактов Microsoft :

Контракты Контракт похож на соглашение между одним или несколькими приложениями. Контракты определяют требования, которым должны соответствовать приложения, чтобы участвовать в этих уникальных взаимодействиях Windows.

Например, Windows позволяет пользователям обмениваться контентом из одного приложения в другое. Приложение, которое совместно использует контент, поддерживает исходный контракт, выполняя определенные требования, в то время как приложение, которое получает общий контент, поддерживает целевой контракт, выполняя другой набор требований. Ни одному приложению не нужно ничего знать о другом. Каждое приложение, которое участвует в договоре о совместном использовании, может быть уверенным в том, что рабочий процесс совместного использования полностью поддерживается, сквозной, Windows.

Интересно, что это звучит как «управляемый интерфейс» между приложением и операционной системой Windows. Для наших приложений доступно 5 контрактов:

  • Выбор файлов
  • Играть
  • Поиск
  • настройки
  • Поделиться

Точно так же, как типичный интерфейс программирования, это означает, что тот, кто расширяет его, использует какой-то тип функциональности, а другой фактически не знает об этом.

В Windows 8 все это выглядит так, как будто это происходит на уровне взаимодействия с пользователем. Что я имею в виду? Что ж, давайте возьмем в качестве примера контракт на акции. Проще говоря, приложения сообщают операционной системе, на что они хотели бы подписаться. В случае обмена, возможно, это принятие изображения или обмена изображением. Windows тогда будет брокером остального.

Представьте себе сценарий, в котором вы найдете отличную статью во время просмотра веб-страниц в чем-то вроде Internet Explorer. Вы хотите поделиться этим с кем-либо по электронной почте или в Twitter. Предполагая, что у вас установлено приложение, которое работает с электронной почтой или Twitter, и они приняли совместное использование URI, тогда Internet Explorer может поделиться с ними. Более того, эти приложения даже не должны быть запущены для этого. Windows позаботится о том, чтобы все это удивительное соус произошло

Похоже на типичный интерфейс программирования, не так ли?

Starting Simple

If you look around at many of the examples out there, you’re going to find a complex set of methods spanning multiple pages, and if you’re anything like me, it’s going to be confusing.  This series of articles is meant to make topics like these simple to understand and use, so I’m going to do just that.

When our application starts up, there is a method in our App.xaml.cs file named OnLaunched that gets fired.  At the very beginning of OnLaunched, we are going to create an event handler for when the user attempts to open the SettingsPane.  Your elements are not added until the user tries to open the Settings Charm.  This event would also be used when you need to “pause” your app or game when the settings are opened.

protected override void OnLaunched(LaunchActivatedEventArgs args)
{
    SettingsPane.GetForCurrentView().CommandsRequested += App_CommandsRequested;
            
    Frame rootFrame = Window.Current.Content as Frame;
 
    ...

 

Once you’ve added the event handler, we can get down to adding SettingsCommands to our SettingsPane.  There are several steps to create a SettingsCommand:

  • Create a new SettingsCommand.  These require three properties: an ID, a label, and an action to perform when the command is pressed.  In our case, this will be creating a Popup control, populating it with a custom UserControl we will create, and sliding it in from the side of the screen.
  • Handle all of the cases for Popup dismissal.  We will also need to make sure that we clean up our mess, so we will need to manage how to get back to our application when the user has indicated they are done.

If you haven’t already generated it, you now need a method for your event handler named App_CommandsRequested, or whatever you chose to name it.  This is where we will do the bulk of our logic for getting the SettingsPane to behave the way we want.  Here’s what mine looks like:

void App_CommandsRequested(SettingsPane sender, SettingsPaneCommandsRequestedEventArgs args)
{
    SettingsCommand command = new SettingsCommand("about", "About This App", (handler) =>
    {
        Popup popup = BuildSettingsItem(new AboutPage(), 646);
        popup.IsOpen = true;
    });
 
    args.Request.ApplicationCommands.Add(command);
}
 

As you can see above, we create a new SettingsCommand object, and provide it with three values.  Unless you plan on changing your SettingsPane at runtime, the first one won’t matter to you much.  It’s a simple ID that you can use to reference the SettingsCommand later.  The label, “About This App,” can be any string value, but I would recommend keeping it under 40 characters, because more than that will be truncated.  Finally, we have our handler for this command.  This is the code that will be executed when the user taps on the label.  I’ve simplified this process by using a lambda expression to define the code inline, and you can see that I am creating a Popup control and setting its IsOpen property to true.  Changing this property is what makes the Popup appear on the screen.

Creating the Popup Control

In this section, we are going to take a look at the BuildSettingsItem method that I have created.  You may have noticed in that code sample above that we are passing two values.  The first is a custom UserControl that we will be creating shortly.  For now, just understand that AboutPage.xaml is a UserControl that we will have to create, and that it is used to populate our Popup control.

private Popup BuildSettingsItem(UserControl u, int w)
{
    Popup p = new Popup();
    p.IsLightDismissEnabled = true;
    p.ChildTransitions = new TransitionCollection();
    p.ChildTransitions.Add(new PaneThemeTransition()
    {
        Edge = (SettingsPane.Edge == SettingsEdgeLocation.Right) ?
                EdgeTransitionLocation.Right :
                EdgeTransitionLocation.Left
    });
 
    u.Width = w;
    u.Height = Window.Current.Bounds.Height;
    p.Child = u;
 
    p.SetValue(Canvas.LeftProperty, SettingsPane.Edge == SettingsEdgeLocation.Right ? (Window.Current.Bounds.Width - w) : 0);
    p.SetValue(Canvas.TopProperty, 0);
 
    return p;
}

Much of the code in this method is “fluffy,” which is to say it’s for making the UI a little more pretty and fluid.  The specific lines that are important are the last six.  We define the height and width of our UserControl, u, and then assign it as a child of our Popup control, p.  (Width is recommended to be 346 or 646, height should be the full height of the user’s screen, according to the guidance from Microsoft.)   Finally, we set the left and top properties of the popup so that it appears in the appropriate location, and pass the entire Popup back to our SettingsCommand.

SIDE NOTE: Windows 8 can actually transform a bit based on the localization settings that have been applied to the machine.  In countries where the language is read from right to left, the Charms Bar is actually located on the left side of the screen instead of the right.  This is why, when assigning the LeftProperty of our Popup, we have to check to see which “edge” the SettingsPane lives on.  You should see similar logic for the Edge of the PaneThemeTransition earlier in the method.

You certainly don’t have to break all of this code up into chunks like I have, but I think it makes things simpler, especially when you want to create multiple SettingsCommand elements.

Creating the UserControl

I promised earlier that we’d come back to this, and here we are.  At this point, we’ve taken care of all the scaffolding that is required to make the Settings Contract work.  Now all we have to do is build a page to be shown.  Add a new UserControl item to your project.  I’ve named mine AboutPage.xaml to match the code we wrote earlier, but you can use any name you’d like obviously.

5-AddUserControl

The code for this file is entirely up to you.  While there are recommendations on how your Settings panels should look, there aren’t any specific rules about it.  What I am providing you in the following code sample is a template of sorts.  It will make your application look like this:

5-SettingsPanelShowing

Ultimately, however, you can use any XAML code that you’d like to make your Popup shine.

<Border BorderBrush="#00b2f0" BorderThickness="1,0,0,0">
    <Grid Background="White" VerticalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*" />
        </Grid.RowDefinitions>
            
        <!-- HEADER -->
        <Grid Background="#00b2f0" Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*" />
            </Grid.ColumnDefinitions>
 
            <StackPanel Orientation="Horizontal" Grid.Column="0" Margin="40, 32, 17, 13">
                <Button x:Name="BackButton" Margin="0,3,0,0" Style="{StaticResource BackButtonStyle}" Click="BackButton_Click"/>
                <TextBlock Margin="10,10,0,0" FontFamily="Segoe UI" FontWeight="SemiLight" FontSize="24.6667" Text="About This App" Foreground="White"/>
            </StackPanel>
            <Image Source="Assets/SmallLogo.png" Width="29" Height="29" Margin="353,46,17,21" />
        </Grid>
 
        <!-- CONTENT AREA -->
        <ScrollViewer VerticalScrollBarVisibility="Auto" Grid.Row="1">
            <Grid Margin="40,33,40,39" VerticalAlignment="Top" Grid.RowSpan="3">
                <StackPanel>
                        
                </StackPanel>
            </Grid>
        </ScrollViewer>
    </Grid>
</Border>

There’s nothing substantially complicated about this layout…we have three controls that are actually important for the header:

  • Button – The Button control is the circled arrow.  We’ve rigged up a click event for this named BackButton_Click, and I’ll show you that code in the final step of this article.
  • TextBlock – This contains the name of the Settings the user is actively looking at.  In most cases, this should match the words that you show in the SettingsPane.
  • Image – This image certainly isn’t required, but constant reinforcement of your branding and logo goes a long way.  I can’t recommend showing your logo as often as possible, and this is a great place to do so.

At the bottom, we have a section marked Content Area.  Inside the embedded StackPanel control is where you should add your content.  This can be anything, but try to keep it simple.  CheckBox, ToggleButton, TextBox, RadioButton, etc.  Simple controls with an eye on performing one simple task.

Here’s the code for the BackButton_Click method:

private void BackButton_Click(object sender, RoutedEventArgs e)
{
    Popup parent = this.Parent as Popup;
    if (parent != null)
    {
        parent.IsOpen = false;
    }
 
    // If the app is not snapped, then the back button shows the Settings pane again.
    if (Windows.UI.ViewManagement.ApplicationView.Value != Windows.UI.ViewManagement.ApplicationViewState.Snapped)
    {
        SettingsPane.Show();
    }
}

You can see that we close our parent Popup control, and if the app is not currently in a snapped state, re-open the SettingsPane, as a good back button should.  So that’s about it!

Oh.  Wait.  You wanted to know how to SAVE the user’s data?

Saving Data

Windows 8 has changed many things, but one of the core user behaviors that has gone away is the concept of a “Save” button.  As much as possible, I want you to eliminate that concept from your mind.

When a user changes a value in their settings,

DO NOT wait for them to click a “Save” button.

DO NOT prompt them with an “Are you sure?” dialog box when the change is reversible.

Save the data the moment they change it, and give your user enough credit to make the changes they want to make.  If they click a “delete all your data” option, that might be a reason to confirm that they’re sure.  But only do it because it’s not reversible.  Not because you think your user is an idiot.

As for the HOW, we’re going to wait on that topic until Day #8, and then we will spend the entire time focused on saving data both locally on the device, as well as roaming those values across all of the machines the user has an account on.

Summary

When I was first introduced to Windows 8 I kept hearing the phrase, “Win as 1”. Win as 1 is one of the core tenets for  Windows. At first this just sounds like standard  marketing speak but actually it’s really far from that. Having now worked with Windows 8 for some time, the contracts are great proof point of this tenet. Things like application settings are now centralized for the user, our applications can now spend more time focusing on delivering their core features rather than dealing with things like settings. Furthermore, now that the settings are consistent across all applications, we only ever have to teach a user once to use settings across all applications.

“I only had to be taught how to open a door once and then I could open all doors.”

— I made that up.

Today, we took a look the Settings Contract, which is just one of many contracts you will find in Windows 8. Just like a programming interface, contracts in Windows 8 offer your app a unique way to extend your application beyond the traditional definition of an “application process” while providing a consistent user interface to our users.

You can download the entire sample solution here here:

 downloadXAML

Tomorrow, we’re going to look at the Search contract.  Search is something you’ll come to find great value in, not only from a usability perspective, but also because it’s a great way to continue to get your application in front of your users. See you then!