質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.37%

WPF XAML : Binding文字列の一部のBindingについて

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,239

yamamoto_001

score 17

VB.NET + WPF + XAML (MVVM prismフレームワーク)で開発しております。

DataGrid内のある列内の文字列の一部に特定の文字列が含まれている場合、そこをHyperlinkにしてCommandをバインドするということが
出来ないか模索しております。
何か良い方法があればご教授お願い致します。

例)

Public Class Person
    Public Property Name As String
    Public Property Description As String
End Class

Public Property Persons As New List(Of Person)

Public Sub New()
Persons.Add(New Person() With { .Name="織田信長", .Description="織田信長は、(注%織田弾正忠家の当主%)・(注%織田信秀の子%)に生まれ、・・・"})
Persons.Add(New Person() With { .Name="豊臣秀吉", .Description="初め(注%木下氏%)で、後に(注%羽柴氏%)に改める。・・・"})
End Sub
    <DataGrid HeadersVisibility="Column" VerticalAlignment="Top" HorizontalAlignment="Left" 
        AutoGenerateColumns="False" CanUserSortColumns="False" CanUserResizeColumns="False" CanUserAddRows="False"
        ItemsSource="{Binding Path=Persons}">
        <DataGrid.Columns>
           <DataGridTextColumn Header="名前" Binding="{Binding Path=Name}"/>
           <DataGridTemplateColumn Header="説明">
               <DataGridTemplateColumn.CellTemplate>
                   <DataTemplate>
                       <TextBlock Text="{Binding Path=Description}"/> 'ここを(注%〇〇〇%)の部分だけHyperlinkにしてCommand={Binding viewCommand} CommandParameter="〇〇〇" みたいにしたい
                   </DataTemplate>
               </DataGridTemplateColumn.CellTemplate>
           </DataGridTemplateColumn>
        </DataGrid.Columns>

質問内容の修正依頼をいただきましたので、加筆させていただきます。

上記例の場合、(注%木下氏%) や(注%羽柴氏%)のように中身が異なる特定の文字列として複数存在します。
(”木下氏”や”羽柴氏"の部分のみ異なる)
Description内での(注%〇△%)の数は決まっていません。(0個の場合もあるし、10個の場合もある)
中身はすべて異なる場合もありますし、一部重複する可能性もあります。

Bindするコマンドは1つで中身をコマンドパラメータでと考えています。

以上、よろしくお願い致します。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • ebiryo

    2019/06/05 10:52

    Descriptionの中には「特定の文字列」は複数存在するのでしょうか。
    複数存在する場合、その文字列はすべて異なる可能性はあるのでしょうか。
    すべて異なる可能性がある場合、Bindするコマンドも複数存在するのでしょうか。

    キャンセル

回答 2

checkベストアンサー

+2

通常のTextBlockだけでは難しいのでは?
UserControlを作成して自前でDescriptionを解析する以外方法はないように思います。

簡単なサンプルを作ってみました。それらしく動作していように思います。
※手慣れたC#で作りましたが、本質な違いはないはず。

ご参考までに。

<!-- Gridに配置するUserControl -->
<UserControl x:Class="WpfApplication1.HyperLinkEx"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApplication1"
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <TextBlock Name="_Content"/>
</UserControl>
/// <summary>
/// HyperLinkEx.xaml の相互作用ロジック
/// </summary>
public partial class HyperLinkEx : UserControl
{
    /// <summary>
    /// Descriptiontとして表示する文字列
    /// </summary>
    public string TextContent
    {
        get { return (string)GetValue(TextContentProperty); }
        set { SetValue(TextContentProperty, value); }
    }
    public static readonly DependencyProperty TextContentProperty =
        DependencyProperty.Register("TextContent", typeof(string), typeof(HyperLinkEx), new PropertyMetadata(null,(v1,v2)=> 
        {
            (v1 as HyperLinkEx)?.UpdateContents();
        }));


    /// <summary>
    /// 特定文字クリック時に発火するコマンド
    /// </summary>
    public ICommand LinkCommand
    {
        get { return (ICommand )GetValue(LinkCommandProperty); }
        set { SetValue(LinkCommandProperty, value); }
    }
    public static readonly DependencyProperty LinkCommandProperty =
        DependencyProperty.Register("LinkCommand", typeof(ICommand ), typeof(HyperLinkEx), new PropertyMetadata(null,(v1,v2)=> 
        {
            (v1 as HyperLinkEx)?.UpdateContents();
        }));

    public HyperLinkEx()
    {
        InitializeComponent();
    }

    void UpdateContents()
    {
        this._Content.Inlines.Clear();
        if (string.IsNullOrEmpty(this.TextContent) == true || LinkCommand == null)
            return;

        //特定文字用パターン文字列
        var pattern = @"(\%.+?\%)";

        //特定文字とそれ以外に分割
        var items = Regex.Split(TextContent, pattern);

        foreach( var item in items )
        {
            //特定文字ならHyperLink
            if( Regex.Match(item, pattern).Success)
            {
                var hyperlink = new Hyperlink(new Run(item.Replace("%", "")))
                {
                    Command = LinkCommand,
                    CommandParameter = item
                };
                _Content.Inlines.Add(hyperlink);
            }
            else
            {
                _Content.Inlines.Add(new Run(item));
            }
        }
    }
}

使い方:

    <Grid>
        <DataGrid HeadersVisibility="Column" VerticalAlignment="Top" HorizontalAlignment="Left" 
        AutoGenerateColumns="False" CanUserSortColumns="False" CanUserResizeColumns="False" CanUserAddRows="False"
        ItemsSource="{Binding Path=Persons}">
            <DataGrid.Columns>
                <DataGridTextColumn Header="名前" Binding="{Binding Path=Name}"/>
                <DataGridTemplateColumn Header="説明">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <local:HyperLinkEx TextContent="{Binding Path=Description}" LinkCommand="{Binding Path=Command}"/> 
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/06/05 16:32

    教えていただいた方法で実現したかったことがばっちりできました。
    迅速で丁寧なご回答本当にありがとうございました。

    キャンセル

0

それなりに手間のかかる仕事になります。FlowDocument をホストするカスタムコントロールを作ってデータテンプレートとして使うことになるのではないでしょうか。勉強する気があるならしてもいいし、する気がないなら他の UI を考えるかプロに頼まなければいけないかもしれません。

方法: ハイパーリンクに下線を引くかどうかを指定する

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.37%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る