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

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

ただいまの
回答率

89.05%

ListView(GridView)で隣の項目へのBinding

解決済

回答 2

投稿 編集

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

nekome4

score 16

イメージ的には以下のようにしたいのですがバインディングされません。
どのようにしたらよいのでしょうか?

サンプルコード

<ListView Height="100" Width="200">
    <ListView.View>
        <GridView>
            <GridViewColumn  Width="100">
                <GridViewColumnHeader Content="項目1"/>
                <GridViewColumn.CellTemplate>
                    <DataTemplate >
                        <TextBlock Text="{Binding ElementName=B, Path=Text}"/>
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
            <GridViewColumn Width="100">
                <GridViewColumnHeader Content="項目2" />
                <GridViewColumn.CellTemplate>
                    <DataTemplate>
                        <TextBox x:Name="B" />
                    </DataTemplate>
                </GridViewColumn.CellTemplate>
            </GridViewColumn>
        </GridView>
    </ListView.View>
</ListView>

追記

例えば、以下に示したデータを適当に入れて項目を生成しておきます。
TextBoxに何か入力したら左側の項目1のTextBlockに同じテキストを表示するようにしたいのですがこの記述(ElmentNameでの指定)ではうまくいかないようです。
よくよく考えれば列ごとに同じNameが設定されるのでできない理由はなんとなくわかるのですが・・。
いろいろ調べて他にRelativeSourceなど試してみましたがこちらでは対応できないようでした。

<Grid>
    <Grid.Resources>
        <XmlDataProvider x:Key="test" XPath="/test/item" >
            <x:XData>
                <test xmlns="">
                    <item foo="hoge"/>
                    <item foo="piyo"/>
                </test>
            </x:XData>
        </XmlDataProvider>
    </Grid.Resources>
    <ListView Height="100" Width="200" ItemsSource="{Binding Source={StaticResource test}}">
        <ListView.View>
            <GridView>
                <GridViewColumn  Width="100">
                    <GridViewColumnHeader Content="項目1"/>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate >
                            <TextBlock Text="{Binding ElementName=B, Path=Text}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Width="100">
                    <GridViewColumnHeader Content="項目2"/>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox x:Name="B" Text="{Binding XPath=@foo, UpdateSourceTrigger=PropertyChanged}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>


偶然↑のコード書いてて気が付いたのですが以下のようにTextBlockに「{Binding XPath=@foo}」を指定すればうまくいきました。
しかし、StyleやContextMenuなどオブジェクトを指定するようなプロパティの場合その方法ではうまくいかないようでした。
そもそもXPathでのやり方は何か違う?ような気が・・・、かと言ってElementNameでの指定も無理がありそうですし・・・。

<Grid>
    <Grid.Resources>
        <XmlDataProvider x:Key="test" XPath="/test/item" >
            <x:XData>
                <test xmlns="">
                    <item foo="hoge"/>
                    <item foo="piyo"/>
                </test>
            </x:XData>
        </XmlDataProvider>
        <Style TargetType="TextBox" x:Key="c">
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu>
                        <MenuItem Header="1"/>
                    </ContextMenu>
                </Setter.Value>
            </Setter>
        </Style>
    </Grid.Resources>
    <ListView Height="100" Width="200" ItemsSource="{Binding Source={StaticResource test}}">
        <ListView.View>
            <GridView>
                <GridViewColumn  Width="100">
                    <GridViewColumnHeader Content="項目1"/>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate >
                            <TextBlock Text="{Binding XPath=@foo}" ContextMenu="{Binding ElementName=B, Path=ContextMenu, Mode=OneWay}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
                <GridViewColumn Width="100">
                    <GridViewColumnHeader Content="項目2"/>
                    <GridViewColumn.CellTemplate>
                        <DataTemplate>
                            <TextBox x:Name="B" Text="{Binding XPath=@foo, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource c}"/>
                        </DataTemplate>
                    </GridViewColumn.CellTemplate>
                </GridViewColumn>
            </GridView>
        </ListView.View>
    </ListView>
</Grid>
  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • gaya-K

    2018/10/10 17:23

    ItemsSource にはどんなデータが入るんでしょうか? また、マークダウンで表も書けるので所望の表を表現してくれませんか。

    キャンセル

  • nekome4

    2018/10/10 20:44

    ご返信ありがとうございます。コード等編集し直しましたのでお願いいたします。

    キャンセル

  • gaya-K

    2018/10/11 20:39

    修正みましたが、そもそも DataGrid を使う理由は何でしょう?本来は VM 側に定義されたデータを表示するための機能なので、提示された使い方は用途に合致してない印象です。

    キャンセル

  • nekome4

    2018/10/12 00:00

    おっしゃる通り本来はそのように使う予定です。ただ、今回はその過程でこういったバインディングはどうしたら実現できるのだろうという素朴な疑問から生まれました。何か自分が見落としているようなバインディング方法があれば教示していただきたいという思いで質問した次第です。

    キャンセル

回答 2

+2

https://teratail.com/questions/146477

何のイメージか知りませんが、違う質問ですか?

意図通り動かないコードをサンプルとして挙げられて「このように」と言われてもどうにもなりませんし、結局何がしたいのかも伝わりません。
過去の質問もちゃんと解決してください。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/10/06 02:44

    >意図通り動かないコードをサンプルとして挙げられて「このように」と言われてもどうにもなりませんし、結局何がしたいのかも伝わりません。

    意図通りに動かないのでそのコードを添付し、質問内容からどう間違っているのかを教示していただきたいのです。
    質問内容がわかりにくかったのなら申し訳ありません。
    しかし、そのような姿勢(発言)をとられるのは私含めこのページを見てくれた人に不快な思いをさせるのでやめてください。

    >過去の質問もちゃんと解決してください。
    こちらも多忙なため確認が遅れただけです。さきほど先にこちらに質問してから確認をとっていました。

    キャンセル

  • 2018/10/06 03:28

    そのような態度は見る人を不快にさせるだけなのでやめてください。

    イメージとして動かないソースを載せて何の意味がありますか?
    動くソースか、日本語での説明をしてください。
    あなたの脳内は言葉にしなければ伝わりません。

    キャンセル

  • 2018/10/06 03:30

    それと、多忙かどうかも言葉にして伝えないとこっちの知ったことではありません。

    長期間放置したときは新たな質問を先にするのではなく、古い質問を解決してからにしてください。
    当然のことだと思いますが。

    キャンセル

checkベストアンサー

+1

結論から言いますと、隣の項目へバインドするのはとても難しいと思いますが、同じ情報を表示することは可能です。


「隣の項目へバインド」とは、サンプルコード中のTextBlockからTextBoxへのバインドの事です。各コントロールに x:Name で定義される名前はネームスコープというものを持っており、XAML内のどこでも参照できる訳ではありません。サンプルのTextBlockとTextBoxは別々のDataTemplateに定義されていますが、Templateが異なるとネームスコープが異なるため、ElementNameで発見できなくなります。これが、サンプルソースがバインドできない理由です。
参考:WPF XAMLネームスコープ

RelativeSourceは、nekome4さんもおっしゃっていますができません。これはビジュアルツリー上の祖先方向の要素を探索してバインドすることはできますが、子孫方向への探索はできません。今回の両コントロールはそれぞれ別のGridViewColumnに定義されていますので、祖先方向に探索しても目的のコントロールに到達できないため、バインディングソースに指定できません。


「同じ情報を表示可能」とは、nekome4さんも発見していますが、XPathでのバインディングのことです。この方法は何ら間違いではなく、むしろ正しい方法です。ListViewはItemsSourceにバインドされたコレクションを元に、各行のビジュアル要素(ListViewItem)を生成します。その際、各ListViewItemのDataContextにはItemsSourceの対応する行のデータが設定されます。このListViewItemの中にTextBlockとTextBoxが生成されるため、これらのコントロールのDataContextには同じ行のデータが設定されています。なので、それぞれのコントロールのプロパティで同じBindngを書けば同じデータがバインドされることになります。別々の場所に同じデータが表示されているだけです。


StyleやContextMenuがバインドできない理由も同じです。これらのプロパティの場合はResourceに定義するなどで対応可能だと思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/19 12:04

    今回のような方法で隣の項目へのバインドが難しいという理由がよくわかりました。
    また、同じデータを表示するという事からVMにデータを中継(OneWay,OneWayTouSource)するためのプロパティをもうけても同じ事ができそうですね。

    詳しくしご説明していただき参考になりました。ありがとうございました。

    キャンセル

  • 2018/11/19 20:51

    納得していただけたようで何よりです。
    VMのプロパティでも同じことができるというよりは、本来はそうやって使うものだと思います。MVVMの考え方としてはデータは全てModelにあり、ViewModelはそれをViewに公開するものだからです(ここは間違っているかもしれませんが、私はそう解釈しています…)。Viewに直接データを埋め込むのは、私の場合ComboBoxやTabControlで仕様上項目が変化し得ない時くらいですね。そういう時も、ComboBoxItemやTabItemを直接XAMLに記述してしまいます。

    キャンセル

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

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

関連した質問

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