トップ回答者
Expander のHeaderTemplateでBinding

質問
-
初歩的な質問ですみません。
ユーザーコントロール内のExpanderのヘッダーにTextBoxを配置し、DataContext(ViewModel)のStringプロパティとバインドさせたいと考えています。
そこで、ExpanderにDataTemplateを設定し、TextBoxを配置して、ViewModelのプロパティとバインドさせるため、下記のように記述したのですが、バインドできず、空のTextBoxが表示されてしまいました。
(TitleStringというのは、ViewModelのString型のプロパティです。set 時にOnPropertyChanged("TitleString"); を行っています)
<UserControl> <UserControl.Resources> <DataTemplate x:Key="ExpanderDataTemplate"> <Grid> <TextBox Text="{Binding Path=TitleString }"/> </Grid> </DataTemplate> </UserControl.Resources> <Grid x:Name="LayoutRoot"> <Expander HeaderTemplate="{DynamicResource ExpanderDataTemplate}"> (Expanderの中身) </Expander> </Grid> </UserControl>
試しに、下記のようにExpanderの中身としてTextBoxを配置し、UserControlのDataContext(ViewModel)のプロパティをバインドさせると中身が反映されますので、このユーザーコントロールのDataContextには正しく値が設定されているようです。
<TextBox x:Name="Title1" Text="{Binding TitleString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
DataTemplateの書式が間違ってますか?
おわかりになりましたら、ご指摘ください。よろしくお願いします。- 編集済み NIM5 2009年8月4日 15:54
回答
すべての返信
-
返信ありがとうございます。
ご指摘いただいたページや、HeaderedContentControl.Header のヘルプなどを参考にして試してみたところ、下記のように記述すると、DataContextのプロパティに応じてExpander内のTextBlockの文字が更新されました。
<UserControl.Resources> <DataTemplate x:Key="ExpanderDataTemplate"> <TextBox Text="{Binding Mode=OneWay}" /> </DataTemplate> </UserControl.Resources> <Grid x:Name="LayoutRoot"> <Expander HeaderTemplate="{DynamicResource ExpanderDataTemplate}" Header="{Binding TitleString}"> (中身) </Expander>
しかし、DataContext → ExpanderのTextBox.Text の一方向バインドのため、Expander内のTextBoxに文字を入力しても、DataContextのプロパティには反映されません。
そこで、双方向バインドにすべく、下記のように書き直したところ、{"両方向のバインドには、Path または XPath が必要です。"} という例外が発生してしまいました。
<DataTemplate x:Key="ExpanderDataTemplate"> <TextBox Text="{Binding Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> </DataTemplate>
バインド先のPathというのは、この場合何を指定すればいいでしょうか?
バインドしたいDataContextのプロパティは、String TitleString; なので、
{Binding Path = TitleString, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
としてみましたが、空のTextBoxが表示されてしまいました。- 編集済み NIM5 2009年8月5日 5:53
-
早速の返信ありがとうございます。
<DataTemplate x:Key="ExpanderDataTemplate"> <TextBox Text="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/> </DataTemplate>
上記のように記述したところ、例外は発生しませんでしたが、片方向バインドになってしまいました。
つまり、DataContext → ExpanderのTextBox は 反映されるのですが、ExpanderのTextBox → DataContext は反映されません。
フォーカスを外しても反映されてないので、アップデートのタイミングというわけでもなさそうです。
↓もやってみましたが、なぜか OneWayになってしまいますね・・・
<TextBox Text="{Binding Path=.}"/>
<TextBox Text="{Binding Path=., Mode=Default}"/>
なにか、別の所で問題があるのかと思い、XAMLのみでシンプルなテストをしてみました。
全コードは↓です。
<Window 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" x:Class="WPF_Expander.MainWindow" x:Name="Window" Title="MainWindow" mc:Ignorable="d"> <Window.Resources> <DataTemplate x:Key="DataTemplate1"> <TextBox Text="{Binding Path=., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> </DataTemplate> </Window.Resources> <StackPanel x:Name="LayoutRoot"> <Expander Header="{Binding Text, ElementName=MainWndText, Mode=Default}" HeaderTemplate="{DynamicResource DataTemplate1}"> <Grid/> </Expander> <TextBox x:Name="MainWndText" Text="TextBox" /> </StackPanel> </Window>
これでもやはり、 MainWindowのTextBox → ExpanderのTextBox は反映されますが、ExpanderのTextBox → MainWindowのTextBox は反映されません・・・
Binding Path=. を、Binding . としても結果は同じでした。 -
ありがとうございます。
Hongliang さんのおっしゃるとおり、Header ではPathを指定せず、DataTemplate でPathを指定したところ、思った通りの動作になりました。
↓のテストでも、実際のアプリでも、どちらでもうまく双方向バインドしてくれました。
<Window 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" x:Class="WPF_Expander.MainWindow" x:Name="Window" Title="MainWindow" mc:Ignorable="d"> <Window.Resources> <DataTemplate x:Key="DataTemplate1"> <TextBox Text="{Binding Text, ElementName=MainWndText,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> </DataTemplate> </Window.Resources> <StackPanel x:Name="LayoutRoot"> <Expander Header="{Binding}" HeaderTemplate="{DynamicResource DataTemplate1}"> <Grid/> </Expander> <TextBox x:Name="MainWndText" Text="TextBox" /> <TextBox x:Name="MainWndText2" Text="{Binding Text, ElementName=MainWndText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" /> </StackPanel> </Window>
Hongliangさん、trapemiyaさん、ありがとうございました。