-1

I have a style which includes two TextBoxes in order to create a PlaceHolder / Watermark, so far is working fine.
The only exception is that the events are triggered twice, the first one comes from the CustomTextBox I have in the Style, and the second one from the CustomTextBox I have in XAML.

Is there any way to prevent this behaviour? I have already tried to set IsEnable="False" and ReadOnly="True" but doesn't seems to work.

Here the style I use to simulate the Watermark:

<Style x:Key="CustomTextBoxStyle"
       TargetType="{x:Type utils:CustomTextBox}">
    <Setter Property="FontFamily"
            Value="/UserInterface;component/Resources/Fonts/#Avenir LT Std 35 Light" />
    <Setter Property="FontSize"
            Value="16" />
    <Setter Property="Foreground"
            Value="#FF414042" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type utils:CustomTextBox}">
                <Border Name="Border"
                        BorderBrush="#FF348781"
                        BorderThickness="0,0,0,4"
                        CornerRadius="2">
                    <ScrollViewer x:Name="PART_ContentHost"
                                  Margin="0" />
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal" />
                            <VisualState x:Name="Disabled" />
                            <VisualState x:Name="ReadOnly" />
                            <VisualState x:Name="MouseOver" />
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style TargetType="{x:Type utils:CustomTextBox}"
       BasedOn="{StaticResource CustomTextBoxStyle}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type utils:CustomTextBox}">
                <Grid>
                    <utils:CustomTextBox
                        Text="{TemplateBinding Text}"
                        x:Name="textSource"
                        Background="Transparent"
                        Panel.ZIndex="2"
                        Style="{StaticResource CustomTextBoxStyle}"
                        KeyboardViewModel="{TemplateBinding KeyboardViewModel}"/>
                    <utils:CustomTextBox Text="{TemplateBinding HintText}"
                                         Background="{TemplateBinding Background}"
                                         Panel.ZIndex="1"
                                         IsEnabled="False">
                        <utils:CustomTextBox.Style>
                            <Style TargetType="{x:Type utils:CustomTextBox}"
                                   BasedOn="{StaticResource CustomTextBoxStyle}">
                                <Setter Property="Foreground"
                                        Value="Transparent" />
                                <Style.Triggers>
                                    <DataTrigger Binding="{Binding Path=Text, Source={x:Reference textSource}}"
                                                 Value="">
                                        <Setter Property="Foreground"
                                                Value="Gray" />
                                        <Setter Property="HorizontalContentAlignment"
                                                Value="Left" />
                                        <Setter Property="VerticalContentAlignment"
                                                Value="Center" />
                                    </DataTrigger>
                                </Style.Triggers>
                            </Style>
                        </utils:CustomTextBox.Style>
                    </utils:CustomTextBox>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Any help would be appreciated. Thanks in advance.

EDIT 1: Code on the CustomTextBox Class for the Event handling

protected override void OnKeyDown(KeyEventArgs e)
{
    //Filtering "solution"
    if (e.Source is CustomTextBox sourceTextBox && sourceTextBox.Name.Equals("textSource"))
     {
         return;
     }

    base.OnKeyDown(e);

    if (e.Key == Key.Enter && EnterKeyCommand != null)
    {
        if (EnterKeyCommand.CanExecute(null))
        {
            EnterKeyCommand.Execute(null);
        }
    }
}

EDIT 2: Use of the CustomTextBox on my UserControl:

<Utils:CustomTextBox Grid.Row="0"
                             Margin="0,10"
                             KeyboardViewModel="{Binding Path=MainWindowViewModel.KeyboardViewModel}" 
                             HintText="Patient"
                             x:Name="Patient"/>
Nekeniehl
  • 1,633
  • 18
  • 35
  • Are you handling events in the codebehind of your custom control? –  Feb 21 '18 at 12:24
  • Show Codbehind? – Liquid Core Feb 21 '18 at 12:24
  • Updated with the code behind in the CustomTextBox. – Nekeniehl Feb 21 '18 at 12:26
  • Have you tried setting IsReadOnly = True??? – Amol Bavannavar Feb 21 '18 at 12:27
  • Thanks @AmolBavannavar, just test it out, still not working. – Nekeniehl Feb 21 '18 at 12:28
  • If you're handling view logic, you should do it in your codebehind file, not your ViewModel. Try using e.Handled = true after doing your logic but it will prevent event bubbling. –  Feb 21 '18 at 12:29
  • That make the trick @IamDOM. If there is no other side effect than the event bubling its okey, as I do not have to bubble it. – Nekeniehl Feb 21 '18 at 12:31
  • Downvoters should explain why the downvoting. – Nekeniehl Feb 21 '18 at 12:32
  • Sure, go ahead and if you can explain side effects would be amazing – Nekeniehl Feb 21 '18 at 12:34
  • Use x:Name on HintTest CustomTextBox, and check the source in CustomTextBox.KeyDown/KeyUp or whichever event.. If it's coming from HintTest, handle that particular event using e.Handled = True... – Amol Bavannavar Feb 21 '18 at 12:36
  • check that using "WPF Tree Visualizer" feature.. – Amol Bavannavar Feb 21 '18 at 12:50
  • I just make another edit to my question. – Nekeniehl Feb 21 '18 at 12:50
  • Why can't you use TextBlock for HintText?? – Amol Bavannavar Feb 21 '18 at 12:51
  • I will give a try. – Nekeniehl Feb 21 '18 at 12:53
  • Works the same, but the events still triggering twice, one from the "testSource" and another one from the CustomTextBox in XAML =( – Nekeniehl Feb 21 '18 at 13:03
  • I think we all learned a lesson about trying to answer low quality answers. It's just waste of time because the only one who can understand his mess is OP. This question is unlikely to help anyone. –  Feb 21 '18 at 14:24
  • You can ask about that mess you are saying, I think we are all here to learn, specially me. I have provided all the necessary code and explain everything, so I dont see your point. – Nekeniehl Feb 21 '18 at 14:28
  • If you're willing to learn, start here: https://stackoverflow.com/help/mcve. I didn't downvote your question but I used to be upset when people downvoted mine but the truth is they were low quality. The number of not proper answers you got just proves my point. If you want feedback, I'm giving you one. –  Feb 21 '18 at 14:31
  • Now I see your point, but not agree with it, I have provided the necessary code to create a minimal example (actually I cannot post more regarding the "too much code" error), I have point it out where the error might be and I have edited and answer any question regarding the matter. But I appreciate your feedback and I will try to do it better next time. – Nekeniehl Feb 21 '18 at 14:37

2 Answers2

0

Based on your comment, first it comes from the "test source" and then goes to CustomTextBox means that the KeyDown event is received on first user control and then passed to the second user control.

Can you make sure that you put e.Handled = true in the "test source" to notify that it is handled on the first user control?

kurakura88
  • 2,185
  • 2
  • 12
  • 18
  • Sure, it was one of the suggestion, I can check `e.Source!="testSource"` but it doesn't seems to be the proper way, basically, I would like to understand why the event is triggering from the CustomTextBox inside the Style. – Nekeniehl Feb 21 '18 at 13:55
-1

"Fixed" filtering the e.Source as sugesstion from @Amol Bavannavar on the comments:

protected override void OnKeyDown(KeyEventArgs e)
{
    if (e.Source is CustomTextBox sourceTextBox && sourceTextBox.Name.Equals("textSource"))
    {
        return;
    }

    base.OnKeyDown(e);

    if (e.Key == Key.Enter && EnterKeyCommand != null)
    {
        if (EnterKeyCommand.CanExecute(null))
        {
            EnterKeyCommand.Execute(null);
        }
    }
}
Stephen Kennedy
  • 20,585
  • 22
  • 95
  • 108
Nekeniehl
  • 1,633
  • 18
  • 35