wpf custom control not show validation error












0















Validation error will not show if I transfer Binding through Dependency Property in custom control.



DETAIL



I have a viewmodel which always have a validation error on one property



class ViewModel : IDataErrorInfo
{
public string Value { get; set; }

public string Error
{
get { return null; }
}

public string this[string columnName]
{
get { return "Error"; }
}
}


and a TextBox on view



<TextBox 
Text="{Binding Value,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}" />


so it will be surrounded by a red border.



ui picture



Then I created a custom control named WrappedTextBox which contains a Text Dependency Property



class WrappedTextBox : Control
{
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}

public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(
"Text",
typeof(string),
typeof(WrappedTextBox));
}


and template



<Style TargetType="local:WrappedTextBox">
<Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:WrappedTextBox">
<Grid>
<AdornerDecorator>
<TextBox
Text="{Binding Text,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True,
RelativeSource={RelativeSource Mode=TemplatedParent}}" />
</AdornerDecorator>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>


put it on view



<local:WrappedTextBox
Text="{Binding Value,
Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
ValidatesOnDataErrors=True,
NotifyOnValidationError=True}" />


as the picture above shows, the second control has no red border on it.



if I don't remove Validation.ErrorTemplate of WrappedTextBox, it will be



picture 2



How do I show error template on TextBox inside WrappedTextBox?










share|improve this question



























    0















    Validation error will not show if I transfer Binding through Dependency Property in custom control.



    DETAIL



    I have a viewmodel which always have a validation error on one property



    class ViewModel : IDataErrorInfo
    {
    public string Value { get; set; }

    public string Error
    {
    get { return null; }
    }

    public string this[string columnName]
    {
    get { return "Error"; }
    }
    }


    and a TextBox on view



    <TextBox 
    Text="{Binding Value,
    Mode=TwoWay,
    UpdateSourceTrigger=PropertyChanged,
    ValidatesOnDataErrors=True,
    NotifyOnValidationError=True}" />


    so it will be surrounded by a red border.



    ui picture



    Then I created a custom control named WrappedTextBox which contains a Text Dependency Property



    class WrappedTextBox : Control
    {
    public string Text
    {
    get { return (string)GetValue(TextProperty); }
    set { SetValue(TextProperty, value); }
    }

    public static readonly DependencyProperty TextProperty =
    DependencyProperty.Register(
    "Text",
    typeof(string),
    typeof(WrappedTextBox));
    }


    and template



    <Style TargetType="local:WrappedTextBox">
    <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="local:WrappedTextBox">
    <Grid>
    <AdornerDecorator>
    <TextBox
    Text="{Binding Text,
    Mode=TwoWay,
    UpdateSourceTrigger=PropertyChanged,
    ValidatesOnDataErrors=True,
    NotifyOnValidationError=True,
    RelativeSource={RelativeSource Mode=TemplatedParent}}" />
    </AdornerDecorator>
    </Grid>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>


    put it on view



    <local:WrappedTextBox
    Text="{Binding Value,
    Mode=TwoWay,
    UpdateSourceTrigger=PropertyChanged,
    ValidatesOnDataErrors=True,
    NotifyOnValidationError=True}" />


    as the picture above shows, the second control has no red border on it.



    if I don't remove Validation.ErrorTemplate of WrappedTextBox, it will be



    picture 2



    How do I show error template on TextBox inside WrappedTextBox?










    share|improve this question

























      0












      0








      0








      Validation error will not show if I transfer Binding through Dependency Property in custom control.



      DETAIL



      I have a viewmodel which always have a validation error on one property



      class ViewModel : IDataErrorInfo
      {
      public string Value { get; set; }

      public string Error
      {
      get { return null; }
      }

      public string this[string columnName]
      {
      get { return "Error"; }
      }
      }


      and a TextBox on view



      <TextBox 
      Text="{Binding Value,
      Mode=TwoWay,
      UpdateSourceTrigger=PropertyChanged,
      ValidatesOnDataErrors=True,
      NotifyOnValidationError=True}" />


      so it will be surrounded by a red border.



      ui picture



      Then I created a custom control named WrappedTextBox which contains a Text Dependency Property



      class WrappedTextBox : Control
      {
      public string Text
      {
      get { return (string)GetValue(TextProperty); }
      set { SetValue(TextProperty, value); }
      }

      public static readonly DependencyProperty TextProperty =
      DependencyProperty.Register(
      "Text",
      typeof(string),
      typeof(WrappedTextBox));
      }


      and template



      <Style TargetType="local:WrappedTextBox">
      <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
      <Setter Property="Template">
      <Setter.Value>
      <ControlTemplate TargetType="local:WrappedTextBox">
      <Grid>
      <AdornerDecorator>
      <TextBox
      Text="{Binding Text,
      Mode=TwoWay,
      UpdateSourceTrigger=PropertyChanged,
      ValidatesOnDataErrors=True,
      NotifyOnValidationError=True,
      RelativeSource={RelativeSource Mode=TemplatedParent}}" />
      </AdornerDecorator>
      </Grid>
      </ControlTemplate>
      </Setter.Value>
      </Setter>
      </Style>


      put it on view



      <local:WrappedTextBox
      Text="{Binding Value,
      Mode=TwoWay,
      UpdateSourceTrigger=PropertyChanged,
      ValidatesOnDataErrors=True,
      NotifyOnValidationError=True}" />


      as the picture above shows, the second control has no red border on it.



      if I don't remove Validation.ErrorTemplate of WrappedTextBox, it will be



      picture 2



      How do I show error template on TextBox inside WrappedTextBox?










      share|improve this question














      Validation error will not show if I transfer Binding through Dependency Property in custom control.



      DETAIL



      I have a viewmodel which always have a validation error on one property



      class ViewModel : IDataErrorInfo
      {
      public string Value { get; set; }

      public string Error
      {
      get { return null; }
      }

      public string this[string columnName]
      {
      get { return "Error"; }
      }
      }


      and a TextBox on view



      <TextBox 
      Text="{Binding Value,
      Mode=TwoWay,
      UpdateSourceTrigger=PropertyChanged,
      ValidatesOnDataErrors=True,
      NotifyOnValidationError=True}" />


      so it will be surrounded by a red border.



      ui picture



      Then I created a custom control named WrappedTextBox which contains a Text Dependency Property



      class WrappedTextBox : Control
      {
      public string Text
      {
      get { return (string)GetValue(TextProperty); }
      set { SetValue(TextProperty, value); }
      }

      public static readonly DependencyProperty TextProperty =
      DependencyProperty.Register(
      "Text",
      typeof(string),
      typeof(WrappedTextBox));
      }


      and template



      <Style TargetType="local:WrappedTextBox">
      <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
      <Setter Property="Template">
      <Setter.Value>
      <ControlTemplate TargetType="local:WrappedTextBox">
      <Grid>
      <AdornerDecorator>
      <TextBox
      Text="{Binding Text,
      Mode=TwoWay,
      UpdateSourceTrigger=PropertyChanged,
      ValidatesOnDataErrors=True,
      NotifyOnValidationError=True,
      RelativeSource={RelativeSource Mode=TemplatedParent}}" />
      </AdornerDecorator>
      </Grid>
      </ControlTemplate>
      </Setter.Value>
      </Setter>
      </Style>


      put it on view



      <local:WrappedTextBox
      Text="{Binding Value,
      Mode=TwoWay,
      UpdateSourceTrigger=PropertyChanged,
      ValidatesOnDataErrors=True,
      NotifyOnValidationError=True}" />


      as the picture above shows, the second control has no red border on it.



      if I don't remove Validation.ErrorTemplate of WrappedTextBox, it will be



      picture 2



      How do I show error template on TextBox inside WrappedTextBox?







      wpf xaml






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Dec 29 '18 at 8:43









      runerbackrunerback

      22829




      22829
























          1 Answer
          1






          active

          oldest

          votes


















          0














          As far as I know your problem is that IDataErrorInfo needs to be implemented on the class you are binding to, in your ControlTemplate you are binding to the Text-Property of your WrappedTextBox, therefore your WrappedTextBox itself has to implement IDataErrorInfo to make validation work on your TextBox.



          Read also this article what you also can do instead of creating a new control.



          For what you want to achieve 2 options came to my mind (Note: This options are created under the assumption that you are doing more stuff so the options of the previously mentioned article does not apply to you)



          Option 1: Derive direct from TextBox



          Code behind:



          class WrappedTextBox : TextBox
          {

          }




          Style:



          <Style TargetType="local:WrappedTextBox" BasedOn="{StaticResource {x:Type TextBox}}">
          <Setter Property="Template">
          <Setter.Value>
          <ControlTemplate TargetType="{x:Type TextBox}">
          <AdornerDecorator>
          <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
          <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
          </Border>
          </AdornerDecorator>
          <-- ControlTemplate.Triggers etc. -->
          </ControlTemplate>
          </Setter.Value>
          </Setter>
          </Style>


          Usage: (same as before)



          <local:WrappedTextBox
          Text="{Binding Value,
          Mode=TwoWay,
          UpdateSourceTrigger=PropertyChanged,
          ValidatesOnDataErrors=True,
          NotifyOnValidationError=True}" />


          Option 2: Pass the Binding itself



          Code behind:



          [TemplatePart(Name = "PART_TEXTBOX", Type = typeof(TextBox))]
          class WrappedTextBox : Control
          {
          private TextBox _partTextBox;

          private BindingBase _textBinding;
          public BindingBase TextBinding
          {
          get => _textBinding;
          set
          {
          if (_textBinding != value)
          {
          _textBinding = value;
          ApplyTextBinding();
          }
          }
          }

          public override void OnApplyTemplate()
          {
          base.OnApplyTemplate();
          _partTextBox = base.GetTemplateChild("PART_TEXTBOX") as TextBox;
          ApplyTextBinding();
          }

          private void ApplyTextBinding()
          {
          if (_partTextBox != null)
          BindingOperations.SetBinding(_partTextBox, TextBox.TextProperty, _textBinding);
          }
          }




          Style:



          <Style TargetType="local:WrappedTextBox">
          <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
          <Setter Property="Template">
          <Setter.Value>
          <ControlTemplate TargetType="local:WrappedTextBox">
          <Grid>
          <AdornerDecorator>
          <TextBox x:Name="PART_TEXTBOX" />
          </AdornerDecorator>
          </Grid>
          </ControlTemplate>
          </Setter.Value>
          </Setter>
          </Style>




          Usage:



          <local:WrappedTextBox
          TextBinding="{Binding Value,
          Mode=TwoWay,
          UpdateSourceTrigger=PropertyChanged,
          ValidatesOnDataErrors=True,
          NotifyOnValidationError=True}" />





          share|improve this answer

























            Your Answer






            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "1"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: true,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: 10,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53968056%2fwpf-custom-control-not-show-validation-error%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            1 Answer
            1






            active

            oldest

            votes








            1 Answer
            1






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            0














            As far as I know your problem is that IDataErrorInfo needs to be implemented on the class you are binding to, in your ControlTemplate you are binding to the Text-Property of your WrappedTextBox, therefore your WrappedTextBox itself has to implement IDataErrorInfo to make validation work on your TextBox.



            Read also this article what you also can do instead of creating a new control.



            For what you want to achieve 2 options came to my mind (Note: This options are created under the assumption that you are doing more stuff so the options of the previously mentioned article does not apply to you)



            Option 1: Derive direct from TextBox



            Code behind:



            class WrappedTextBox : TextBox
            {

            }




            Style:



            <Style TargetType="local:WrappedTextBox" BasedOn="{StaticResource {x:Type TextBox}}">
            <Setter Property="Template">
            <Setter.Value>
            <ControlTemplate TargetType="{x:Type TextBox}">
            <AdornerDecorator>
            <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
            <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
            </Border>
            </AdornerDecorator>
            <-- ControlTemplate.Triggers etc. -->
            </ControlTemplate>
            </Setter.Value>
            </Setter>
            </Style>


            Usage: (same as before)



            <local:WrappedTextBox
            Text="{Binding Value,
            Mode=TwoWay,
            UpdateSourceTrigger=PropertyChanged,
            ValidatesOnDataErrors=True,
            NotifyOnValidationError=True}" />


            Option 2: Pass the Binding itself



            Code behind:



            [TemplatePart(Name = "PART_TEXTBOX", Type = typeof(TextBox))]
            class WrappedTextBox : Control
            {
            private TextBox _partTextBox;

            private BindingBase _textBinding;
            public BindingBase TextBinding
            {
            get => _textBinding;
            set
            {
            if (_textBinding != value)
            {
            _textBinding = value;
            ApplyTextBinding();
            }
            }
            }

            public override void OnApplyTemplate()
            {
            base.OnApplyTemplate();
            _partTextBox = base.GetTemplateChild("PART_TEXTBOX") as TextBox;
            ApplyTextBinding();
            }

            private void ApplyTextBinding()
            {
            if (_partTextBox != null)
            BindingOperations.SetBinding(_partTextBox, TextBox.TextProperty, _textBinding);
            }
            }




            Style:



            <Style TargetType="local:WrappedTextBox">
            <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
            <Setter Property="Template">
            <Setter.Value>
            <ControlTemplate TargetType="local:WrappedTextBox">
            <Grid>
            <AdornerDecorator>
            <TextBox x:Name="PART_TEXTBOX" />
            </AdornerDecorator>
            </Grid>
            </ControlTemplate>
            </Setter.Value>
            </Setter>
            </Style>




            Usage:



            <local:WrappedTextBox
            TextBinding="{Binding Value,
            Mode=TwoWay,
            UpdateSourceTrigger=PropertyChanged,
            ValidatesOnDataErrors=True,
            NotifyOnValidationError=True}" />





            share|improve this answer






























              0














              As far as I know your problem is that IDataErrorInfo needs to be implemented on the class you are binding to, in your ControlTemplate you are binding to the Text-Property of your WrappedTextBox, therefore your WrappedTextBox itself has to implement IDataErrorInfo to make validation work on your TextBox.



              Read also this article what you also can do instead of creating a new control.



              For what you want to achieve 2 options came to my mind (Note: This options are created under the assumption that you are doing more stuff so the options of the previously mentioned article does not apply to you)



              Option 1: Derive direct from TextBox



              Code behind:



              class WrappedTextBox : TextBox
              {

              }




              Style:



              <Style TargetType="local:WrappedTextBox" BasedOn="{StaticResource {x:Type TextBox}}">
              <Setter Property="Template">
              <Setter.Value>
              <ControlTemplate TargetType="{x:Type TextBox}">
              <AdornerDecorator>
              <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
              <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
              </Border>
              </AdornerDecorator>
              <-- ControlTemplate.Triggers etc. -->
              </ControlTemplate>
              </Setter.Value>
              </Setter>
              </Style>


              Usage: (same as before)



              <local:WrappedTextBox
              Text="{Binding Value,
              Mode=TwoWay,
              UpdateSourceTrigger=PropertyChanged,
              ValidatesOnDataErrors=True,
              NotifyOnValidationError=True}" />


              Option 2: Pass the Binding itself



              Code behind:



              [TemplatePart(Name = "PART_TEXTBOX", Type = typeof(TextBox))]
              class WrappedTextBox : Control
              {
              private TextBox _partTextBox;

              private BindingBase _textBinding;
              public BindingBase TextBinding
              {
              get => _textBinding;
              set
              {
              if (_textBinding != value)
              {
              _textBinding = value;
              ApplyTextBinding();
              }
              }
              }

              public override void OnApplyTemplate()
              {
              base.OnApplyTemplate();
              _partTextBox = base.GetTemplateChild("PART_TEXTBOX") as TextBox;
              ApplyTextBinding();
              }

              private void ApplyTextBinding()
              {
              if (_partTextBox != null)
              BindingOperations.SetBinding(_partTextBox, TextBox.TextProperty, _textBinding);
              }
              }




              Style:



              <Style TargetType="local:WrappedTextBox">
              <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
              <Setter Property="Template">
              <Setter.Value>
              <ControlTemplate TargetType="local:WrappedTextBox">
              <Grid>
              <AdornerDecorator>
              <TextBox x:Name="PART_TEXTBOX" />
              </AdornerDecorator>
              </Grid>
              </ControlTemplate>
              </Setter.Value>
              </Setter>
              </Style>




              Usage:



              <local:WrappedTextBox
              TextBinding="{Binding Value,
              Mode=TwoWay,
              UpdateSourceTrigger=PropertyChanged,
              ValidatesOnDataErrors=True,
              NotifyOnValidationError=True}" />





              share|improve this answer




























                0












                0








                0







                As far as I know your problem is that IDataErrorInfo needs to be implemented on the class you are binding to, in your ControlTemplate you are binding to the Text-Property of your WrappedTextBox, therefore your WrappedTextBox itself has to implement IDataErrorInfo to make validation work on your TextBox.



                Read also this article what you also can do instead of creating a new control.



                For what you want to achieve 2 options came to my mind (Note: This options are created under the assumption that you are doing more stuff so the options of the previously mentioned article does not apply to you)



                Option 1: Derive direct from TextBox



                Code behind:



                class WrappedTextBox : TextBox
                {

                }




                Style:



                <Style TargetType="local:WrappedTextBox" BasedOn="{StaticResource {x:Type TextBox}}">
                <Setter Property="Template">
                <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                <AdornerDecorator>
                <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                </Border>
                </AdornerDecorator>
                <-- ControlTemplate.Triggers etc. -->
                </ControlTemplate>
                </Setter.Value>
                </Setter>
                </Style>


                Usage: (same as before)



                <local:WrappedTextBox
                Text="{Binding Value,
                Mode=TwoWay,
                UpdateSourceTrigger=PropertyChanged,
                ValidatesOnDataErrors=True,
                NotifyOnValidationError=True}" />


                Option 2: Pass the Binding itself



                Code behind:



                [TemplatePart(Name = "PART_TEXTBOX", Type = typeof(TextBox))]
                class WrappedTextBox : Control
                {
                private TextBox _partTextBox;

                private BindingBase _textBinding;
                public BindingBase TextBinding
                {
                get => _textBinding;
                set
                {
                if (_textBinding != value)
                {
                _textBinding = value;
                ApplyTextBinding();
                }
                }
                }

                public override void OnApplyTemplate()
                {
                base.OnApplyTemplate();
                _partTextBox = base.GetTemplateChild("PART_TEXTBOX") as TextBox;
                ApplyTextBinding();
                }

                private void ApplyTextBinding()
                {
                if (_partTextBox != null)
                BindingOperations.SetBinding(_partTextBox, TextBox.TextProperty, _textBinding);
                }
                }




                Style:



                <Style TargetType="local:WrappedTextBox">
                <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
                <Setter Property="Template">
                <Setter.Value>
                <ControlTemplate TargetType="local:WrappedTextBox">
                <Grid>
                <AdornerDecorator>
                <TextBox x:Name="PART_TEXTBOX" />
                </AdornerDecorator>
                </Grid>
                </ControlTemplate>
                </Setter.Value>
                </Setter>
                </Style>




                Usage:



                <local:WrappedTextBox
                TextBinding="{Binding Value,
                Mode=TwoWay,
                UpdateSourceTrigger=PropertyChanged,
                ValidatesOnDataErrors=True,
                NotifyOnValidationError=True}" />





                share|improve this answer















                As far as I know your problem is that IDataErrorInfo needs to be implemented on the class you are binding to, in your ControlTemplate you are binding to the Text-Property of your WrappedTextBox, therefore your WrappedTextBox itself has to implement IDataErrorInfo to make validation work on your TextBox.



                Read also this article what you also can do instead of creating a new control.



                For what you want to achieve 2 options came to my mind (Note: This options are created under the assumption that you are doing more stuff so the options of the previously mentioned article does not apply to you)



                Option 1: Derive direct from TextBox



                Code behind:



                class WrappedTextBox : TextBox
                {

                }




                Style:



                <Style TargetType="local:WrappedTextBox" BasedOn="{StaticResource {x:Type TextBox}}">
                <Setter Property="Template">
                <Setter.Value>
                <ControlTemplate TargetType="{x:Type TextBox}">
                <AdornerDecorator>
                <Border x:Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" SnapsToDevicePixels="True">
                <ScrollViewer x:Name="PART_ContentHost" Focusable="false" HorizontalScrollBarVisibility="Hidden" VerticalScrollBarVisibility="Hidden"/>
                </Border>
                </AdornerDecorator>
                <-- ControlTemplate.Triggers etc. -->
                </ControlTemplate>
                </Setter.Value>
                </Setter>
                </Style>


                Usage: (same as before)



                <local:WrappedTextBox
                Text="{Binding Value,
                Mode=TwoWay,
                UpdateSourceTrigger=PropertyChanged,
                ValidatesOnDataErrors=True,
                NotifyOnValidationError=True}" />


                Option 2: Pass the Binding itself



                Code behind:



                [TemplatePart(Name = "PART_TEXTBOX", Type = typeof(TextBox))]
                class WrappedTextBox : Control
                {
                private TextBox _partTextBox;

                private BindingBase _textBinding;
                public BindingBase TextBinding
                {
                get => _textBinding;
                set
                {
                if (_textBinding != value)
                {
                _textBinding = value;
                ApplyTextBinding();
                }
                }
                }

                public override void OnApplyTemplate()
                {
                base.OnApplyTemplate();
                _partTextBox = base.GetTemplateChild("PART_TEXTBOX") as TextBox;
                ApplyTextBinding();
                }

                private void ApplyTextBinding()
                {
                if (_partTextBox != null)
                BindingOperations.SetBinding(_partTextBox, TextBox.TextProperty, _textBinding);
                }
                }




                Style:



                <Style TargetType="local:WrappedTextBox">
                <Setter Property="Validation.ErrorTemplate" Value="{x:Null}" />
                <Setter Property="Template">
                <Setter.Value>
                <ControlTemplate TargetType="local:WrappedTextBox">
                <Grid>
                <AdornerDecorator>
                <TextBox x:Name="PART_TEXTBOX" />
                </AdornerDecorator>
                </Grid>
                </ControlTemplate>
                </Setter.Value>
                </Setter>
                </Style>




                Usage:



                <local:WrappedTextBox
                TextBinding="{Binding Value,
                Mode=TwoWay,
                UpdateSourceTrigger=PropertyChanged,
                ValidatesOnDataErrors=True,
                NotifyOnValidationError=True}" />






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Dec 30 '18 at 19:41

























                answered Dec 30 '18 at 19:34









                nosalenosale

                644212




                644212






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Stack Overflow!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53968056%2fwpf-custom-control-not-show-validation-error%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    Monofisismo

                    Angular Downloading a file using contenturl with Basic Authentication

                    Olmecas