Reputation: 533
I have custom ContentControl
public class FilteringColumnHeader : ContentControl
{
public static readonly DependencyProperty TextFieldProperty =
DependencyProperty.Register("TextField", typeof(string), typeof(FilteringColumnHeader), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));
public string TextField
{
get
{
return (string)GetValue(TextFieldProperty);
}
set { SetValue(TextFieldProperty, value); }
}
}
With this template style
<Style TargetType="{x:Type c:FilteringColumnHeader}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type c:FilteringColumnHeader}">
<DockPanel>
<ContentPresenter DockPanel.Dock="Top" Content="{TemplateBinding Content}" />
<TextBox Text="{TemplateBinding TextField}"/>
</DockPanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And this is how I use it in DataGrid
in XAML
<DataGridTextColumn x:Name="NameColumn" Header="Name" Binding="{Binding Name}" Width="*" MinWidth="50">
<DataGridTextColumn.HeaderTemplate>
<DataTemplate>
<c:FilteringColumnHeader Content="{Binding }" Width="{Binding ActualWidth, ElementName=NameColumn}" TextField="{Binding DataContext.NameFilter, RelativeSource={RelativeSource AncestorType={x:Type local:GeneratorsListView}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>
</DataTemplate>
</DataGridTextColumn.HeaderTemplate>
</DataGridTextColumn>
And GeneratorsListView
private string nameFilter = "rec";
public string NameFilter
{
get { return nameFilter; }
set
{
nameFilter = value;
}
}
My problem is, the Text
binding works only OneWay. When I run the code TextBox will be filled with "rec" and when I change the NameFilter
, the TextBox also changes. But when I type something in that box, nothing happens (setter of NameFilter
is not being invoked at all). As you can see I've tried to set mode to TwoWay
everywhere I could, still nothing. When I pleace regular TextBox
inside DataTemplate
and set the exact same Text binding, it is working.
Upvotes: 0
Views: 677
Reputation: 169160
{TemplateBinding}
is an optimized version of a binding with a mode of OneWay
so if you want the property to get updated you should use an ordinary binding with the RelativeSource
set to TemplatedParent
:
<ControlTemplate TargetType="{x:Type c:FilteringColumnHeader}">
<DockPanel>
<ContentPresenter DockPanel.Dock="Top" Content="{TemplateBinding Content}" />
<TextBox Text="{Binding TextField, UpdateSourceTrigger=PropertyChanged, RelativeSource={RelativeSource TemplatedParent}}"/>
</DockPanel>
</ControlTemplate>
Upvotes: 3