前提・実現したいこと
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
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/11/06 01:42
2020/11/06 03:05