しっぽを追いかけて

ぐるぐるしながら考えています

Unity と猫の話題が中心   掲載内容は個人の私見であり、所属組織の見解ではありません

UWP でプログラマブルに XAML を読み込んで画面に表示したい

ロゴ作成ツールを作るからにはロゴのベクターデータを取り込みたい!

最初は SVG ファイルを取り込みたいと思ったのですが、UWP 対応の Win2D でもまだサポートされる目途がないみたいなので諦め;

しかたがないので、例によって XAML ファイルを取り込むことにしました


取り込む XAML は UWP で扱える形式なら大丈夫なはず・・・今回は次のような手順で作ってみました

Syncfusion 社の Metro Studio*1 なんかで気に入ったロゴをピックアップして

f:id:matatabi_ux:20150929215128p:plain

画面下部の「Code」ボタンで XAML を表示

f:id:matatabi_ux:20150929215346p:plain

左下の「Copy」ボタンで全体をコピーしてテキストエディタにペースト

f:id:matatabi_ux:20150929215538p:plain

先頭の「x:Shared="false"」は UWP にはないディレクティブなので削除して任意のファイル名で保存します。

この XAML ファイルを読み込む XamlViewer という UserControl を次のような感じで作りました(XAML 側は空で大丈夫なはず)

/// <summary>
/// Xaml view control
/// </summary>
public sealed partial class XamlViewer : UserControl
{
    /// <summary>
    /// Source dependency property
    /// </summary>
    public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
        "Source",
        typeof(string),
        typeof(XamlViewer),
        new PropertyMetadata(string.Empty, OnSourceChanged));

    /// <summary>
    /// Source CLR property
    /// </summary>
    public string Source
    {
        get { return (string)this.GetValue(SourceProperty); }
        set { this.SetValue(SourceProperty, value); }
    }

    /// <summary>
    /// Source changed event handler
    /// </summary>
    /// <param name="d">dependency object</param>
    /// <param name="e">event arguments</param>
    private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var control = d as XamlViewer;
        if (control == null || !(e.NewValue is string) || string.IsNullOrEmpty((string)e.NewValue))
        {
            return;
        }
        var content = XamlReader.Load(e.NewValue as string) as FrameworkElement;
        if (content == null)
        {
            return;
        }
        control.Content = content;
    }

    /// <summary>
    /// Constructor
    /// </summary>
    public XamlViewer()
    {
        this.InitializeComponent();
    }
}

依存関係プロパティの Source に XAMLソースコードが設定されたら XamlReader という読み込みクラスを利用して FrameworkElement 化して自分自身の Content に放り込んでいます

XAML ファイル自体の読み込みは下記のような感じ

/// <summary>
/// Add logo symbol image button clicked event handler
/// </summary>
/// <param name="sender">event sender</param>
/// <param name="e">event arguments</param>
private async void OnAddSymbolClick(object sender, RoutedEventArgs e)
{
    var filePicker = new FileOpenPicker
    {
        FileTypeFilter = { ".xaml" },
        ViewMode = PickerViewMode.List,
        SuggestedStartLocation = PickerLocationId.PicturesLibrary,
        CommitButtonText = this.resource.GetString("Button_FilePicker/Content"),
    };
    var file = await filePicker.PickSingleFileAsync();
    if (file == null)
    {
        return;
    }
    using (var stream = await file.OpenStreamForReadAsync())
    {
        var reader = new StreamReader(stream);
        this.xamlViewer.Source = await reader.ReadToEndAsync();
    }
}

FileOpenPicker を使えば簡単ですね

動かしてみましたよ

f:id:matatabi_ux:20150929220715g:plain

すんなり読み込めました

Windows 10 からは FilePicker の OS 標準仕様のダイアログも使えるようになったようですね・・・タブレットモードでも同じようです

*1:メールアドレス等でアカウント登録すれば無料で利用できます