トップ回答者
カスタムコントロールの子要素を別要素へ配置した際のBindingについて

質問
-
お世話になります。
カスタムコントロールを作成しています。
機能の概要はカスタムコントロールの子要素を別要素の子に移動(厳密には移動とちょっと違いますが)するものです。サンプルでは子要素でTextBlockのTextに対してNameを設定したTextBoxのTextをBindingして表示をするものです。
これを実行すると、子要素を移動は行えましたがBindingが意図したものになっていないのか、移動後のTextBlockのTextは表示されません。
(赤枠内のTextBlockには表示され、青枠のTextBlockには表示されない。Bindingが元の状態のままになっている?)このような場合にBindingを再構築(?)させるためにはどうすればよいでしょうか?
<Window x:Class="Sample3" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WPFSample" mc:Ignorable="d" Title="Sample3" Height="300" Width="300"> <Grid> <local:SampleCustom x:Name="SampleCustom1"> <StackPanel Name="Content1"> <TextBox Name="TextBlock1" Text="123456"/> <TextBlock> <Run Text="入力テキスト:"/> <Run Text="{Binding Text,ElementName=TextBlock1}"/> </TextBlock> </StackPanel> </local:SampleCustom> <StackPanel Margin="10"> <Border Name="Border1" BorderBrush="Red" BorderThickness="1" CornerRadius="5" Height="100" Padding="5"> <StackPanel> <TextBlock> <Run Text="入力テキスト:"/> <Run Text="{Binding Text,ElementName=TextBlock1}"/> </TextBlock> </StackPanel> </Border> <Border Name="Border2" BorderBrush="Blue" BorderThickness="1" CornerRadius="5" Height="100" Padding="5" Margin="0,10,0,0" > </Border> <Button Content="表示" Margin="0,10,0,0" Click="Button_Click" /> </StackPanel> </Grid> </Window>
Public Class Sample3 Private Sub Button_Click(sender As Object, e As RoutedEventArgs) SampleCustom1.IsShow = True End Sub End Class
''' <summary> ''' SampleCustomコントロール ''' </summary> ''' <remarks></remarks> <Markup.ContentProperty(NameOf(SampleCustom.Content))> Public Class SampleCustom Inherits System.Windows.Controls.Control Shared Sub New() ''この OverrideMetadata 呼び出しは、この要素が基底クラスと異なるスタイルを提供することをシステムに通知します。 ''このスタイルは themes\generic.xaml に定義されています 'DefaultStyleKeyProperty.OverrideMetadata(GetType(SampleCustom), New FrameworkPropertyMetadata(GetType(SampleCustom))) End Sub Public Overrides Sub OnApplyTemplate() MyBase.OnApplyTemplate() 'ChildContent = GetTemplateChild("PART_XXXXX") End Sub #Region "Content依存プロパティ" ''' <summary> ''' 依存プロパティ コンテンツ ''' </summary> Public Shared ReadOnly ContentProperty As DependencyProperty = DependencyProperty.Register( "Content", GetType(Object), GetType(SampleCustom), New PropertyMetadata(Nothing)) ''' <summary> ''' CRLラッパー コンテンツ ''' </summary> ''' <returns></returns> Public Property Content() As Object Get Return GetValue(ContentProperty) End Get Set(ByVal value As Object) SetValue(ContentProperty, value) End Set End Property #End Region #Region "IsShow依存プロパティ" ''' <summary> ''' 依存プロパティ 表示するかどうか ''' </summary> Public Shared ReadOnly IsShowProperty As DependencyProperty = DependencyProperty.Register( "IsShow", GetType(Boolean), GetType(SampleCustom), New FrameworkPropertyMetadata(False, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, New PropertyChangedCallback(AddressOf OnIsShowChanged))) ''' <summary> ''' CRLラッパー 表示するかどうか ''' </summary> ''' <returns></returns> Public Property IsShow() As Boolean Get Return Convert.ToBoolean(GetValue(IsShowProperty)) End Get Set(ByVal value As Boolean) SetValue(IsShowProperty, value) End Set End Property ''' <summary> ''' IsShowプロパティ変更 ''' </summary> ''' <param name="d"></param> ''' <param name="e"></param> Private Shared Sub OnIsShowChanged(d As DependencyObject, e As DependencyPropertyChangedEventArgs) Dim content = DirectCast(d.GetValue(ContentProperty), DependencyObject) Dim insertTarget = d.Parents.OfType(Of Window).First.Descendants.OfType(Of Border).Where(Function(x) x.Name = "Border2").First insertTarget.Child = content End Sub #End Region End Class
Module DependencyObjectExtensions ''' <summary> ''' 親要素を取得 ''' </summary> ''' <param name="d">依存関係プロパティ システムに関連するオブジェクト</param> ''' <returns></returns> <Runtime.CompilerServices.Extension> Public Iterator Function Parents(d As DependencyObject) As IEnumerable(Of DependencyObject) If d Is Nothing Then Throw New ArgumentNullException(NameOf(d)) End If Dim pre = d Do pre = VisualTreeHelper.GetParent(pre) If Not IsNothing(pre) Then Yield pre Else Exit Do End If Loop End Function ''' <summary> ''' 子要素を取得 ''' </summary> ''' <param name="d"></param> ''' <returns></returns> <Runtime.CompilerServices.Extension> Public Iterator Function Children(d As DependencyObject) As IEnumerable(Of DependencyObject) If d Is Nothing Then Throw New ArgumentNullException(NameOf(d)) End If Dim count = VisualTreeHelper.GetChildrenCount(d) If count = 0 Then Exit Function End If For i As Integer = 0 To count - 1 Dim child = VisualTreeHelper.GetChild(d, i) If Not IsNothing(child) Then Yield child End If Next End Function ''' <summary> ''' 子孫要素を取得 ''' </summary> ''' <param name="d"></param> ''' <returns></returns> <Runtime.CompilerServices.Extension> Public Iterator Function Descendants(d As DependencyObject) As IEnumerable(Of DependencyObject) If d Is Nothing Then Throw New ArgumentNullException(NameOf(d)) End If For Each child In d.Children() Yield child For Each grandChild In child.Descendants() Yield grandChild Next Next End Function End Module
- 編集済み mikupedia 2016年8月10日 2:53
回答
すべての返信
-
こんにちは。
調べてみたところカスタムコントロールのContent内でBindingSourceが設定されていないので、
おそらくElementNameが使えないのだと思います。x:Referenceを変わりに使ってみてはどうでしょうか。
<StackPanel Name="Content1"> <TextBox Name="TextBlock1" Text="123456"/> <TextBlock> <Run Text="入力テキスト:"/> <!--<Run Text="{Binding Text,ElementName=TextBlock1}"/>--> <Run Text="{Binding Text}" DataContext="{x:Reference Name=TextBlock1}" /> </TextBlock> </StackPanel>
- 回答の候補に設定 ShiroYuki_Mot 2016年8月10日 5:44