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

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

新規登録して質問してみよう
ただいま回答率
85.35%
UWP

UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

データバインディング

データソースと、アプリケーションやウェブページ(ウェブアプリケーション)のユーザインタフェースを静的または動的に結合する技術です。

button

HTMLで用いる<button>タグです。

Q&A

解決済

1回答

2597閲覧

DataTemplateにUserControlを使用する場合、UserControl内のプロパティを使用する側からxamlで定義する方法

hirotamasami

総合スコア5

UWP

UWPは、Universal Windows Platformの略。様々なデバイス向けに提供されているアプリケーションを共通のフレームワーク上で動作可能にする仕組みで、Windows10で導入されました。

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

XAML

XAML(Extensible Application Markup Language)はWPF、Silverlight、Windows PhoneそしてWindows Store appsでユーザーインターフェースを定義するために使われるXML言語です。

データバインディング

データソースと、アプリケーションやウェブページ(ウェブアプリケーション)のユーザインタフェースを静的または動的に結合する技術です。

button

HTMLで用いる<button>タグです。

1グッド

0クリップ

投稿2020/11/05 04:38

前提・実現したいこと

UWPで以下のようにListViewで使用するDataTemplateを作成しました。

C#

1<Page 2 x:Class="TestTemplateInUserCon.MainPage" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="using:TestTemplateInUserCon" 6 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 mc:Ignorable="d" 9 Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 10 11 <GridView x:Name="bb" ItemsSource="{x:Bind ViewDataList}"> 12 <ItemsControl.ItemTemplate> 13 <DataTemplate x:DataType="local:ViewData"> 14 <Button> 15 <Grid> 16 <Grid.RowDefinitions> 17 <RowDefinition Height="3*"/> 18 <RowDefinition Height="1*"/> 19 </Grid.RowDefinitions> 20 21 <Image Grid.Row="0" 22 Source="{x:Bind Image}"/> 23 24 <Grid Grid.Row="1" 25 Background="White"> 26 <TextBlock Text="{x:Bind Name}" 27 TextAlignment="Center"/> 28 </Grid> 29 30 </Grid> 31 </Button> 32 </DataTemplate> 33 </ItemsControl.ItemTemplate> 34 </GridView> 35</Page> 36 37using Windows.UI.Xaml.Media; 38 39namespace TestTemplateInUserCon 40{ 41 public class ViewData 42 { 43 public string Name { get; set; } 44 public ImageSource Image { get; set; } 45 } 46}

上記のようなものを作成するにあたって
DataTemplate内で定義するコンポーネントを
自作のButtonコントロール(UserControl?)にして作成しようと考え
以下のような形で作成しました。

C#

1<Button 2 x:Class="TestTemplateInUserCon.TempButton" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="using:TestTemplateInUserCon" 6 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 mc:Ignorable="d"> 9 10 <Button.DataContext> 11 <local:TempButtonViewModel/> 12 </Button.DataContext> 13 14 <Grid> 15 <Grid.RowDefinitions> 16 <RowDefinition Height="3*"/> 17 <RowDefinition Height="1*"/> 18 </Grid.RowDefinitions> 19 20 <Image Grid.Row="0" 21 Source="{Binding TargetImage}"/> 22 23 <Grid Grid.Row="1" 24 Background="White"> 25 <TextBlock Text="{Binding TargetName}" 26 TextAlignment="Center"/> 27 </Grid> 28 29 </Grid> 30 31</Button> 32 33using Windows.UI.Xaml; 34using Windows.UI.Xaml.Controls; 35 36namespace TestTemplateInUserCon 37{ 38 public sealed partial class TempButton : Button 39 { 40 public readonly DependencyProperty ItemProperty = 41 DependencyProperty.Register( 42 "Item", 43 typeof(ViewData), 44 typeof(TempButton), 45 new PropertyMetadata(default(ViewData), OnSourceChanged)); 46 47 public ViewData Item 48 { 49 get { return (ViewData)GetValue(ItemProperty); } 50 set { SetValue(ItemProperty, value); } 51 } 52 53 // 依存関係プロパティに値がセットされたときに呼び出されるメソッド 54 private static void OnSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 55 { 56 var thisInstance = (TempButton)d; 57 TempButtonViewModel viewModel = (TempButtonViewModel)thisInstance.DataContext; 58 var data = e.NewValue as ViewData; 59 viewModel.TargetData = data; 60 } 61 62 public TempButton() 63 { 64 this.InitializeComponent(); 65 } 66 } 67} 68 69using Windows.UI.Xaml.Media; 70 71namespace TestTemplateInUserCon 72{ 73 /// <summary>TempButtonViewModel クラスは、TempButtonのViewModelクラスです。</summary> 74 public class TempButtonViewModel 75 { 76 77 private ViewData targetData; 78 public ViewData TargetData 79 { 80 get => targetData; 81 set 82 { 83 targetData = value; 84 if (value != null) 85 { 86 TargetImage = value.Image; 87 TargetName = value.Name; 88 } 89 else 90 { 91 TargetImage = null; 92 TargetName = null; 93 } 94 95 } 96 } 97 98 public ImageSource TargetImage; 99 100 101 public string TargetName { get; set; } 102 103 } 104}

上記のように作成した、
ButtonをPageで

C#

1<Page 2 x:Class="TestTemplateInUserCon.MainPage" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="using:TestTemplateInUserCon" 6 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 mc:Ignorable="d" 9 Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> 10 11 <GridView x:Name="bb" ItemsSource="{x:Bind ViewDataList}"> 12 <ItemsControl.ItemTemplate> 13 <DataTemplate x:DataType="local:ViewData"> 14 <Button> 15 <local:TempButton Item="{Binding }"/> 16 </Button> 17 </DataTemplate> 18 </ItemsControl.ItemTemplate> 19 </GridView> 20</Page>

と使用したところ、
データはバインディングされず
TempButtonに定義したOnSourceChangedを確認してみたところ
e.NewValueはNullとなっておりました。

この状態で
TempButtonのxamlコードにて

C#

1<Button 2 x:Class="TestTemplateInUserCon.TempButton" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 5 xmlns:local="using:TestTemplateInUserCon" 6 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 7 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 8 mc:Ignorable="d"> 9 10 11 12 <Grid> 13 <Grid.RowDefinitions> 14 <RowDefinition Height="3*"/> 15 <RowDefinition Height="1*"/> 16 </Grid.RowDefinitions> 17 18 <Image Grid.Row="0" 19 Source="{Binding TargetImage}"/> 20 21 <Grid Grid.Row="1" 22 Background="White"> 23 <TextBlock Text="{Binding TargetName}" 24 TextAlignment="Center"/> 25 </Grid> 26 27 </Grid> 28 29</Button>

とし、
DataContextへのViewModelの代入を削除したところ
e.ValueにViewDataのインスタンスが入っておりましたが、
OnSourceChangedでのdをキャスト後に取得可能なDataContextにも
同じViewDataの値が代入されておりました。

Button使用側(DataTemplate側)では、確かにItemにデータをバインドさせていると思うのですが、
なぜDataContextにも値がはいっていおり、
DataContextにViewModelを代入してる場合なぜe.ValueはNullになってしまうのでしょうか?

また私の使用方法が間違っているのだと思うのですが、
これらからButton側でDataContextにはViewModel,バインドする値は他で
プロパティを定義する場合
どのようにすればよろしいでしょうか?

このようなサイトでの質問もまだ慣れておらず、情報不足ありましたら
ご指摘ください。
宜しくお願い致します。

補足情報(FW/ツールのバージョンなど)

・OS バージョン Windows10

TN8001👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

DataContextへのViewModelの代入を削除したところ
e.ValueにViewDataのインスタンスが入っておりましたが、

DataContextViewModelを、必ず入れなければならないと思い込んでいるんでしょうか?
ViewDataが入ってきているのですから、そのままバインドすればいいのですが。
つまりDependencyPropertyも不要です。

xml

1<Button 2 x:Class="Questions302443.TempButton" 3 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 4 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 5 <Grid> 6 <Grid.RowDefinitions> 7 <RowDefinition Height="3*" /> 8 <RowDefinition /> 9 </Grid.RowDefinitions> 10 <Image Source="{Binding Image}" /> 11 <Grid Grid.Row="1" Background="White"> 12 <TextBlock Text="{Binding Name}" TextAlignment="Center" /> 13 </Grid> 14 </Grid> 15</Button>

DataContextにViewModelを代入してる場合なぜe.ValueはNullになってしまうのでしょうか?

いいえTempButtonViewModelが入っています。
as ViewDataとしたため、nullになりました。

ListView等のコレクションを扱うコントロールは、個々のアイテムにDataContext経由でデータを渡します。
しかしTempButton内でDataContextを設定した場合は、そちらが優先されてしまいます。

そもそもユーザーコントロールやテンプレートコントロール内で、自身のDataContextを設定すること自体がイレギュラーだと思います(全くないとまでは言えませんが)

投稿2020/11/05 09:17

編集2023/07/23 09:09
TN8001

総合スコア9862

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

hirotamasami

2020/11/06 01:42

ご回答ありがとうございます。 キャスト失敗の結果Nullになってるんですね まだItemに代入したのに e.NewValueになぜViewModelが入ってるのかがわかりませんが、 (eには変更されたプロパティを対象にした値、今回だとItemが入ってると思ってたため) そもそも引数の (DependencyObject d, DependencyPropertyChangedEventArgs e) がなんなのか理解できてない(勘違いしてる)のかもしれません。 これらがなんなのかこの辺をもう少し確認してみます。 ありがとうございました。 また何かございましたらよろしくお願いします。
TN8001

2020/11/06 03:05

>キャスト失敗の結果Nullになってるんですね >まだItemに代入したのに >e.NewValueになぜViewModelが入ってるのかがわかりませんが、 ブレークポイントで止めるか、 Debug.WriteLine(e.NewValue); とでもすれば確認できます。 Item="{Binding}" は、そのDataContextからDataContext自身をバインドするわけですが、 TempButtonができたときにはTempButtonViewModelが設定されているので、それが渡るんだと思います。 詳細は私もわかってないです^^; 型が違っても来るんですねw
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問