Win10 UWP Development Series: Develop a custom control-AppBarButton and win10appbarbutton with digital badges

Source: Internet
Author: User

Win10 UWP Development Series: Develop a custom control-AppBarButton and win10appbarbutton with digital badges

A recent project has such a requirement. There are several appbarbuttons at the bottom of the article browsing page, one of which is the comment button, and a red number needs to be displayed on the comment button, similar new message notifications:

This design is common on iOS and Android platforms, but no ready-made controls are provided on UWP. So you can only implement one.

 

The result is as follows:

 

Analyze the Implementation ideas. First, this is an AppBarButton. It only adds a digital badge display. This attribute can be bound to other attributes. If the bound value is not 0, a number is displayed, if the value is 0, the number is hidden. Therefore, we can implement this control by inheriting the AppBarButton and modifying its template.

 

Let's take a look at it. I have installed the latest VS2017, but it is similar to VS2015. Create a UWP project named AppBarBadgeButtonSample:

Choose to open in Blend:

Add An AppBar on the page:

The structure is as follows:

Then we need to export the default AppBarButton template for our custom controls. Right-click the button and select Edit template to edit the copy:

Enter a name. For simplicity, create this style in the current file. Click OK.

Switch to the XAML mode. You can see that the following resources are added to the page's XAML code:

This is the control template of AppBarButton. We need to implement the custom AppBarBadgeButton based on this default template.

Now return to VS2017, add a folder named Controls in the current project, add a folder named AppBarBadgeButton, and then add a template control:

After confirming, we can see that two files are added to the project, one is the cs file and the other is the xaml file:

This Generic. xaml is the template of the control, but if the template of each control is written here, it will appear messy. It is best to put the cs file and the xaml file of each control in one piece. Therefore, add a style file named AppBarBadgeButton. xaml under the AppBarBadgeButton directory to facilitate management. Change the control namespace from AppBarBadgeButtonSample. Controls. AppBarBadgeButton to AppBarBadgeButtonSample. Controls.

Now we can copy the default template of AppBarButton generated earlier:

Note: To delete the key, replace TargetType with AppBarBadgeButton:

<ResourceDictionary. MergedDictionaries> <ResourceDictionary Source = "ms-appx: // Controls/AppBarBadgeButton. xaml"/> </ResourceDictionary. MergedDictionaries>

 

In this way, the templates of all controls are put together with their own cs files, and only the reference position is put in the Generic. xaml file, so the project structure is much clearer.

 

Now return to AppBarBadgeButton. cs and change the Control base class from Control to AppBarButton. In this way, all the actions of the control are consistent with the default AppBarButton.

We need a numeric attribute and an attribute that controls whether a number is visible. Add the following code:

public string Count{    get { return (string)GetValue(CountProperty); }    set { SetValue(CountProperty, value); }}// Using a DependencyProperty as the backing store for Count.  This enables animation, styling, binding, etc...public static readonly DependencyProperty CountProperty =    DependencyProperty.Register("Count", typeof(string), typeof(AppBarBadgeButton), new PropertyMetadata("0", null));

 

This is a dependency attribute. Note that the numeric type is string? Why is it not set to int?

Sell a customs token. Let's talk about it first.

Now you can modify the template of the control. After carefully analyzing the template, you can find the place to change. There is a Grid named ContentRoot, which should be here. Add a Border and a TextBlock to the ContentPresenter named Content to display the number:

<Border CornerRadius="8" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Top"                                     Background="Red"  Grid.Row="0" MinWidth="16" Height="16">                                <TextBlock HorizontalAlignment="Center" VerticalAlignment="Center"                                           FontSize="10" Text="{TemplateBinding Count}" Foreground="Yellow" />                            </Border>

 

Note: Use TemplateBinding to bind the text to the Count attribute.

Try it now. We set "x: Name" of the Page to "rootPage" and change the AppBarButton added on the home Page to a custom AppBarBadgeButton. Do not forget to introduce the namespace: xmlns: localControls = "using: AppBarBadgeButtonSample. controls"

Set DataContext of Page, add a Count attribute, and bind the Count attribute of AppBarBadgeButton to the Count attribute of the cs file:

Xaml:

<Page    x:Class="AppBarBadgeButtonSample.MainPage"    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"    xmlns:local="using:AppBarBadgeButtonSample"    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    xmlns:localControls="using:AppBarBadgeButtonSample.Controls"    mc:Ignorable="d"    x:Name="rootPage">    <Page.BottomAppBar>        <CommandBar>            <CommandBar.Content>                <Grid/>            </CommandBar.Content>            <localControls:AppBarBadgeButton Icon="Accept" Count="{Binding Count}" Label="AppBarButton"/>            <AppBarButton Icon="Cancel" Label="AppBarButton"/>        </CommandBar>    </Page.BottomAppBar>    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">    </Grid></Page>

 

Cs:

public sealed partial class MainPage : Page{    public MainPage()    {        this.InitializeComponent();        this.Count = 10;        this.rootPage.DataContext = this;    }    public int Count { get; set; }}

 

I didn't use the standard MVVM here, just a simple demonstration. Run the following command:

The result is displayed.

Now let's think about the question just now. Why can we set the attribute in DataContext to int, and the dependency attribute of the control must be set to string? If you are interested, change the dependency attribute to int. The result is that nothing is displayed on the button:

This is because, when using TemplateBinding, you must ensure that the source attribute and target attribute value type match, and TextBlock's Text attribute is string, the type of the property to be bound must also be string. When TemplateBinding is used, there is no chance of automatic type conversion. If the type does not match, it cannot be bound. See: https://docs.microsoft.com/en-us/windows/uwp/xaml-platform/templatebinding-markup-extension

Now we can display numbers, but we still need to improve it. When there is a number, it is displayed. If it is 0, it is hidden. So do a little bit of work:

Add an attribute to control whether a number is displayed:

public Visibility BadgeVisibility{    get { return (Visibility)GetValue(BadgeVisibilityProperty); }    set { SetValue(BadgeVisibilityProperty, value); }}// Using a DependencyProperty as the backing store for BadgeVisibility.  This enables animation, styling, binding, etc...public static readonly DependencyProperty BadgeVisibilityProperty =    DependencyProperty.Register("BadgeVisibility", typeof(Visibility), typeof(AppBarBadgeButton), new PropertyMetadata(Visibility.Collapsed, null));

 

 

When the Count value changes, set it to hide:

public string Count        {            get { return (string)GetValue(CountProperty); }            set { SetValue(CountProperty, value); }        }        // Using a DependencyProperty as the backing store for Count.  This enables animation, styling, binding, etc...        public static readonly DependencyProperty CountProperty =            DependencyProperty.Register("Count", typeof(string), typeof(AppBarBadgeButton), new PropertyMetadata("0", OnCountChanged));        private static void OnCountChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)        {            int count = 0;            int.TryParse(e.NewValue.ToString(), out count);            if (count != 0)            {                ((AppBarBadgeButton)d).SetValue(BadgeVisibilityProperty, Visibility.Visible);            }            else            {                ((AppBarBadgeButton)d).SetValue(BadgeVisibilityProperty, Visibility.Collapsed);            }        } 

 

Finally, bind the Visibility attribute of the number to this value:

<Border CornerRadius="8" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Top"                                     Background="Red" Visibility="{TemplateBinding BadgeVisibility}" Grid.Row="0" MinWidth="16" Height="16">

 

 

Code Open Source: https://github.com/yanxiaodi/UWP-AppBarBadgeButton

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.