Windowsストアアプリ入門 vol71:TextBlockに下線(アンダーライン)をつける

木曜日 , 4, 10月 2012 Leave a comment

 たかがアンダーライン、されどアンダーライン。

 

 TextBlockコントロールはWPFなどの環境ではTextDecorationプロパティで下線の指定ができるので、下線を引くのにあまり困りません。

 しかしWindowsストアアプリの場合、TextDecorationプロパティが無いのでちょっと苦労します。

 

 最終目的は「データバインディングを用いて下線がある場合とない場合を制御したい」なんですが、TextBlockの下線について順を追って説明していきます。

 

 簡単に下線を引くなら以下、

 

        <TextBlock>
            <Underline>下線を引く</Underline>
        </TextBlock>

 

 ついでに下線を一部だけにしたり改行を入れるなら以下のようにも書けます。

 

            <TextBlock FontSize="17.333" Margin="0,30,0,0" >
                <Run Text="一部だけ" />
                <Underline>下線を引く</Underline>
                <LineBreak />
                <Run Text="改行を入れる" />
                <LineBreak/>
            </TextBlock>

 

 以下のように表示されます。

 

 

 コードビハインドからは以下のようにも書けます。

 

            var underline = new Underline();
            var run = new Run();
            run.Text = "コードビハインドから下線を追加";

            underline.Inlines.Add(run);

            this.textBlock.Inlines.Add(underline);

 

 

 そして本題。

 データバィンディングを用いて、条件によって下線を出したり、出さなかったりしたい場合。

 

 簡単なViewModelを以下のように作成する。

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnderlineSample.Common;

namespace UnderlineSample.ViewModels
{
    class MainPageViewModel : BindableBase
    {
        /// <summary>
        /// アンダーラインを引きたい場合こちらに値を入れる
        /// </summary>
        private string _underlineText;

        public string underlineText
        {
            get { return _underlineText; }
            set
            {
                _underlineText = value;
                OnPropertyChanged("underlineText");
            }
        }

        /// <summary>
        /// アンダーラインを引きたくない場合はこちらに値を入れる
        /// </summary>
        private string _normalText;

        public string normalText
        {
            get { return _normalText; }
            set
            {
                _normalText = value;
                OnPropertyChanged("normalText");
            }
        }
    }
}

 

 下線を引く引かないの条件はアプリ毎に色々あると思うけど、今回はわかりやすいように2つのプロパティのどちらかに値を入れることで制御することにした。

 

 XAMLは以下(これまでのサンプルも含む)

 

<Page
    x:Class="UnderlineSample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:UnderlineSample"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:converter="using:UnderlineSample.Common"
    mc:Ignorable="d">
    
    <Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
        <Grid.Resources>
            <converter:StringToVisibilityConverter x:Key="StringToVisibilityConverter" />
        </Grid.Resources>
        <StackPanel Orientation="Vertical">
            <TextBlock FontSize="17.333" >
                <Underline>下線を引く</Underline>
            </TextBlock>
            <TextBlock FontSize="17.333" Margin="0,30,0,0" >
                <Run Text="一部だけ" />
                <Underline>下線を引く</Underline>
                <LineBreak />
                <Run Text="改行を入れる" />
                <LineBreak/>
            </TextBlock>

            <TextBlock x:Name="textBlock"  FontSize="17.333" />

            <TextBlock Visibility="{Binding underlineText, Converter={StaticResource StringToVisibilityConverter}}"  Margin="0,30,0,0" >
                <Underline><Run FontSize="17.333" Text="{Binding underlineText }" /></Underline>
            </TextBlock>

            <TextBlock Visibility="{Binding normalText, Converter={StaticResource StringToVisibilityConverter}}"  Margin="0,30,0,0" >
                <Run  FontSize="17.333" Text="{Binding normalText }" />
            </TextBlock>
        </StackPanel>
    </Grid>
</Page>

 

 見ての通りコンバーターでVisibilityを変えている。

 コンバーターは以下、

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.Graphics.Display;
using Windows.UI.ViewManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Data;

namespace UnderlineSample.Common
{
    public sealed class StringToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if (value is String)
            {
                string str = (string)value;
                Visibility visibility = ((str == null || str == "" || str == string.Empty) == true) ? Visibility.Collapsed : Visibility.Visible;
                return visibility;
            }
            else
            {
                return Visibility.Collapsed;
            }
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            return value is Visibility && (Visibility)value == Visibility.Visible;
        }
    }
}

 

 空文字チェックはこんなに判定いらないだろうなぁと思いつつ・・・

 

 最後に、MainPage.xaml.csで以下のように利用します。

 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using UnderlineSample.ViewModels;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Documents;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

// 空白ページのアイテム テンプレートについては、http://go.microsoft.com/fwlink/?LinkId=234238 を参照してください

namespace UnderlineSample
{
    /// <summary>
    /// それ自体で使用できる空白ページまたはフレーム内に移動できる空白ページ。
    /// </summary>
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            var underline = new Underline();
            var run = new Run();
            run.Text = "コードビハインドから下線を追加";

            underline.Inlines.Add(run);

            this.textBlock.Inlines.Add(underline);

            //this.DataContext = new MainPageViewModel() { underlineText = "アンダーラインを引きたい場合" };
            this.DataContext = new MainPageViewModel() { normalText = "アンダーラインを引きたくない場合" };
        }

        /// <summary>
        /// このページがフレームに表示されるときに呼び出されます。
        /// </summary>
        /// <param name="e">このページにどのように到達したかを説明するイベント データ。Parameter 
        /// プロパティは、通常、ページを構成するために使用します。</param>
        protected override void OnNavigatedTo(NavigationEventArgs e)
        {
        }
    }
}

 

 

 上記コードはプロジェクトを公開していますので全文を見て動かしたい方は以下

 プロジェクトをGitHubで見る

 

 (正直もっとシンプルなやり方あるはずだと思うが見つからなかったので紹介。誰かもっといい方法を知っていたら教えてください)

 


Please give us your valuable comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です