0

public class CustomSearchControl : Control
    {
        static CustomSearchControl()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(CustomSearchControl),
                        new FrameworkPropertyMetadata(typeof(CustomSearchControl)));

            CommandManager.RegisterClassCommandBinding(typeof(CustomSearchControl), 
                        new CommandBinding(CustomSearchControl.DeleteCommand, C_DeleteCommand));
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
        }

        static void C_DeleteCommand(object sender, ExecutedRoutedEventArgs e)
        {
            CustomSearchControl mycontrol = sender as CustomSearchControl;
            mycontrol.SearchText = "";
        }
        public static readonly ICommand DeleteCommand = new RoutedUICommand("DeleteCommand", "DeleteCommand", 
                                    typeof(CustomSearchControl), 
                                            new InputGestureCollection(new InputGesture[] 
                                            { new KeyGesture(Key.Enter), new MouseGesture(MouseAction.LeftClick) }));


        public static readonly DependencyProperty SearchTextProperty =
                    DependencyProperty.Register("SearchText", 
                                                    typeof(string),
                                                    typeof(CustomSearchControl),
                                                    new FrameworkPropertyMetadata(
                                                        null,
                                                        FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                                        SearchTextPropertyChanged));
        public string SearchText
        {
            get { return (string)base.GetValue(SearchTextProperty); }
            set { base.SetValue(SearchTextProperty, value); }
        }

        private static void SearchTextPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
        {
            CustomSearchControl mycontrol = d as CustomSearchControl;
            mycontrol.SearchText = e.NewValue.ToString();
        }
    }
<ResourceDictionary x:Class="CustomSearchControl" 
                    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:local="clr-namespace:WpfApplicationCustomSearchControl">
    
    <Style TargetType="{x:Type local:CustomSearchControl}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:CustomSearchControl}">
                    <Grid>
                        <StackPanel Orientation="Horizontal">
                            <TextBox x:Name="tbSearchTextBox"
                                     Width="200" Height="25"
                                     Text="{TemplateBinding SearchText}">
                            </TextBox>
                            <Button x:Name="btnDelete"
                                    Width="50" Height="25"
                                    Content="Delete"
                                    Command="{x:Static local:CustomSearchControl.DeleteCommand}">
                            </Button>
                        </StackPanel>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ResourceDictionary>

<Window...>
  <Grid>
        <local:CustomSearchControl SearchText="{Binding Path=SearchText, UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}"/>
    </Grid>
</Window>

I want to create a Custom Control with a TextBox and a Button that clears the TextBox. If Text in TextBox changed, the PropertyCallBack isn't raised. The same issue appears, when DeleteCommand is raised.

What's wrong?

Jürgen
  • 3
  • 4
  • *"If Text in TextBox changed, the PropertyCallBack isn't raised"* - this is not clear, can you describe the problem better? Do you mean `Text="{TemplateBinding SearchText, UpdateSourceTrigger=PropertyChanged}"` (see [this](http://stackoverflow.com/a/21030997/1997232))? – Sinatr May 12 '17 at 08:40
  • In MainWindow the SearchTextProperty of CustomControl is binded to a public Property "SearchText" in ViewModel, which has the INotifyPropertyChanged. I mean the method SearchTextPropertyChanged in CustomControl – Jürgen May 12 '17 at 08:51
  • Why do you need callback? `TemplateBinding` will already update `TextBox` (see @Quarzy answer). I understood your question as if you type text and callback is not called (it's not called until binding will update source, therefore my comment of how to do so that you type and it will be updated after each change of `Text`). – Sinatr May 12 '17 at 09:05

2 Answers2

2

I don't really understand what you are trying to achieve, but I believe there is at least one mistake: why are you dealing with SearchTextPropertyChanged?

You can replace:

new FrameworkPropertyMetadata(null,FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,SearchTextPropertyChanged));

by

new FrameworkPropertyMetadata(default(string));

And that's all, the searchText is able to update itself.

In any case, I would suggest you to use a more classical approach using MVVM creating a view and a viewmodel, it will be easier to implement, to test and to maintain.

Ouarzy
  • 3,015
  • 1
  • 16
  • 19
  • Just a note, creating custom control like this with dependency property used only by the view is totally fine. This doesn't require viewmodel. – Sinatr May 12 '17 at 09:07
  • @Quarzy: Your solution works, if i don't bind the SearchTextProperty of my customControl to my SearchTextProperty in ViewModel. I need the binding to ViewModelProperty because with the text in TextBox of my CustomControl I want to fire FilterMethods of Controls in several different UserControls. – Jürgen May 12 '17 at 09:23
  • @Sinatr: I need the Change of TextBox, because i have to implement a filtering for a Control that contains the CustomControl – Jürgen May 12 '17 at 09:34
  • @Jürgen, you can keep everything just remove `mycontrol.SearchText = e.NewValue.ToString()`. Callback is called when `SearchText` dependency property is changed, you **should not** change it again in callback. – Sinatr May 12 '17 at 09:41
  • @Sinatr: thats exactly the issue. if I bind the SearchtextProperty of the CustomControl to a StringProperty for example Binding to filtermethods the changes of the text didn't fired. – Jürgen May 12 '17 at 10:07
  • @Jürgen, ... until `LostFocus` event is fired for `TextBox`? – Sinatr May 12 '17 at 10:14
  • @Sinatr: I have tried binding Text of secondTextBox in UserControl to the SearchTextProperty of the CustomControl: When typing in TextBox of CustomControl there are no Text in the second TextBox. But I have removed the CallBack in CustomControl like Quarzy. – Jürgen May 12 '17 at 10:34
  • @Jürgen, *"in the second TextBox"* - you lost me here. – Sinatr May 12 '17 at 11:09
0

OK I have figured out the issue and solved the Problem. The reason for the issue is the "TemplatedBinding" in TextBox of Generic.xaml.

So first changes in Generic.xaml:

<TextBox Text="{Binding RelativeSource={RelativeSource TemplatedParent},Path=SearchText,Mode=TwoWay,UpdateSourceTrigger=PropertyChanged}">

And second in UserControl binding Searchtext-Property to ViewModel-Property:

<local:CustomSearchControl SearchText="{Binding Path=ViewModelPropertyText,Mode=TwoWay}"/>

Now it works fine and you can bind the SearchText-Property of CustomControl to whatever you want!

Thanks to all who have thought about my issue.

Jürgen
  • 3
  • 4