PropertyChangedCallback of DependencyProperty Ignores Delay Binding












2















I have a user control with a textbox and a custom list control that's basically a ListBox with a CollectionView. I'd like to use the filter functionality of the CollectionView and use the text from the textbox to filter the visible elements.



A simplified representation of the xaml:



<TextBox x:Name="FilterTextControl"/>
<CustomControls:OverviewControl
x:Name="ProfileOverviewControl"
FilterText="{Binding ElementName=FilterTextControl, Path=Text, Mode=OneWay, Delay=5000}"
Items="{Binding AllItems}"/>


The CollectionViewSource:



<CollectionViewSource x:Key="GroupedProfiles"
Source="{Binding Items, RelativeSource={RelativeSource AncestorType=local:OverviewControl}}"
Filter="GroupedProfiles_OnFilter">
<CollectionViewSource.SortDescriptions>
<componentModel:SortDescription PropertyName="Location" />
<componentModel:SortDescription PropertyName="Description" />
</CollectionViewSource.SortDescriptions>
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="Location" />
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>


The FilterText Dependency Property in the OverviewControl:



public string FilterText
{
get => (string)GetValue(FilterTextProperty);
set => SetValue(FilterTextProperty, value);
}

public static readonly DependencyProperty FilterTextProperty =
DependencyProperty.Register(nameof(FilterText), typeof(string),
typeof(ProfileOverviewControl), new FrameworkPropertyMetadata(OnFilterTextChanged));

private static void OnFilterTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var intanceOfThisClass = (ProfileOverviewControl)d;
if (_collectionViewSource == null)
_collectionViewSource = intanceOfThisClass.FindResource("GroupedProfiles") as CollectionViewSource;
_collectionViewSource?.View?.Refresh();
}


The OnFilterEvent method:



    private void GroupedProfiles_OnFilter(object sender, FilterEventArgs e)
{
e.Accepted = string.IsNullOrEmpty(FilterText) || e.Item.ToString().Contains(FilterText);
}


The Problem



As you can see in the binding of the FilterText I have a delay of 5000ms. For testing purposes I've made it 5000ms instead of a reasonable 500ms.
In order for the filter to work I need to refresh the CollectionView.
However the PropertyChangedCallback fires immediately after each change instead of throttling it with the delay binding.



I don't quite understand this behaviour. If this is just how a delay binding works, are there alternatives for throttling the CollectionView refresh?










share|improve this question



























    2















    I have a user control with a textbox and a custom list control that's basically a ListBox with a CollectionView. I'd like to use the filter functionality of the CollectionView and use the text from the textbox to filter the visible elements.



    A simplified representation of the xaml:



    <TextBox x:Name="FilterTextControl"/>
    <CustomControls:OverviewControl
    x:Name="ProfileOverviewControl"
    FilterText="{Binding ElementName=FilterTextControl, Path=Text, Mode=OneWay, Delay=5000}"
    Items="{Binding AllItems}"/>


    The CollectionViewSource:



    <CollectionViewSource x:Key="GroupedProfiles"
    Source="{Binding Items, RelativeSource={RelativeSource AncestorType=local:OverviewControl}}"
    Filter="GroupedProfiles_OnFilter">
    <CollectionViewSource.SortDescriptions>
    <componentModel:SortDescription PropertyName="Location" />
    <componentModel:SortDescription PropertyName="Description" />
    </CollectionViewSource.SortDescriptions>
    <CollectionViewSource.GroupDescriptions>
    <PropertyGroupDescription PropertyName="Location" />
    </CollectionViewSource.GroupDescriptions>
    </CollectionViewSource>


    The FilterText Dependency Property in the OverviewControl:



    public string FilterText
    {
    get => (string)GetValue(FilterTextProperty);
    set => SetValue(FilterTextProperty, value);
    }

    public static readonly DependencyProperty FilterTextProperty =
    DependencyProperty.Register(nameof(FilterText), typeof(string),
    typeof(ProfileOverviewControl), new FrameworkPropertyMetadata(OnFilterTextChanged));

    private static void OnFilterTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
    var intanceOfThisClass = (ProfileOverviewControl)d;
    if (_collectionViewSource == null)
    _collectionViewSource = intanceOfThisClass.FindResource("GroupedProfiles") as CollectionViewSource;
    _collectionViewSource?.View?.Refresh();
    }


    The OnFilterEvent method:



        private void GroupedProfiles_OnFilter(object sender, FilterEventArgs e)
    {
    e.Accepted = string.IsNullOrEmpty(FilterText) || e.Item.ToString().Contains(FilterText);
    }


    The Problem



    As you can see in the binding of the FilterText I have a delay of 5000ms. For testing purposes I've made it 5000ms instead of a reasonable 500ms.
    In order for the filter to work I need to refresh the CollectionView.
    However the PropertyChangedCallback fires immediately after each change instead of throttling it with the delay binding.



    I don't quite understand this behaviour. If this is just how a delay binding works, are there alternatives for throttling the CollectionView refresh?










    share|improve this question

























      2












      2








      2


      1






      I have a user control with a textbox and a custom list control that's basically a ListBox with a CollectionView. I'd like to use the filter functionality of the CollectionView and use the text from the textbox to filter the visible elements.



      A simplified representation of the xaml:



      <TextBox x:Name="FilterTextControl"/>
      <CustomControls:OverviewControl
      x:Name="ProfileOverviewControl"
      FilterText="{Binding ElementName=FilterTextControl, Path=Text, Mode=OneWay, Delay=5000}"
      Items="{Binding AllItems}"/>


      The CollectionViewSource:



      <CollectionViewSource x:Key="GroupedProfiles"
      Source="{Binding Items, RelativeSource={RelativeSource AncestorType=local:OverviewControl}}"
      Filter="GroupedProfiles_OnFilter">
      <CollectionViewSource.SortDescriptions>
      <componentModel:SortDescription PropertyName="Location" />
      <componentModel:SortDescription PropertyName="Description" />
      </CollectionViewSource.SortDescriptions>
      <CollectionViewSource.GroupDescriptions>
      <PropertyGroupDescription PropertyName="Location" />
      </CollectionViewSource.GroupDescriptions>
      </CollectionViewSource>


      The FilterText Dependency Property in the OverviewControl:



      public string FilterText
      {
      get => (string)GetValue(FilterTextProperty);
      set => SetValue(FilterTextProperty, value);
      }

      public static readonly DependencyProperty FilterTextProperty =
      DependencyProperty.Register(nameof(FilterText), typeof(string),
      typeof(ProfileOverviewControl), new FrameworkPropertyMetadata(OnFilterTextChanged));

      private static void OnFilterTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
      var intanceOfThisClass = (ProfileOverviewControl)d;
      if (_collectionViewSource == null)
      _collectionViewSource = intanceOfThisClass.FindResource("GroupedProfiles") as CollectionViewSource;
      _collectionViewSource?.View?.Refresh();
      }


      The OnFilterEvent method:



          private void GroupedProfiles_OnFilter(object sender, FilterEventArgs e)
      {
      e.Accepted = string.IsNullOrEmpty(FilterText) || e.Item.ToString().Contains(FilterText);
      }


      The Problem



      As you can see in the binding of the FilterText I have a delay of 5000ms. For testing purposes I've made it 5000ms instead of a reasonable 500ms.
      In order for the filter to work I need to refresh the CollectionView.
      However the PropertyChangedCallback fires immediately after each change instead of throttling it with the delay binding.



      I don't quite understand this behaviour. If this is just how a delay binding works, are there alternatives for throttling the CollectionView refresh?










      share|improve this question














      I have a user control with a textbox and a custom list control that's basically a ListBox with a CollectionView. I'd like to use the filter functionality of the CollectionView and use the text from the textbox to filter the visible elements.



      A simplified representation of the xaml:



      <TextBox x:Name="FilterTextControl"/>
      <CustomControls:OverviewControl
      x:Name="ProfileOverviewControl"
      FilterText="{Binding ElementName=FilterTextControl, Path=Text, Mode=OneWay, Delay=5000}"
      Items="{Binding AllItems}"/>


      The CollectionViewSource:



      <CollectionViewSource x:Key="GroupedProfiles"
      Source="{Binding Items, RelativeSource={RelativeSource AncestorType=local:OverviewControl}}"
      Filter="GroupedProfiles_OnFilter">
      <CollectionViewSource.SortDescriptions>
      <componentModel:SortDescription PropertyName="Location" />
      <componentModel:SortDescription PropertyName="Description" />
      </CollectionViewSource.SortDescriptions>
      <CollectionViewSource.GroupDescriptions>
      <PropertyGroupDescription PropertyName="Location" />
      </CollectionViewSource.GroupDescriptions>
      </CollectionViewSource>


      The FilterText Dependency Property in the OverviewControl:



      public string FilterText
      {
      get => (string)GetValue(FilterTextProperty);
      set => SetValue(FilterTextProperty, value);
      }

      public static readonly DependencyProperty FilterTextProperty =
      DependencyProperty.Register(nameof(FilterText), typeof(string),
      typeof(ProfileOverviewControl), new FrameworkPropertyMetadata(OnFilterTextChanged));

      private static void OnFilterTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
      {
      var intanceOfThisClass = (ProfileOverviewControl)d;
      if (_collectionViewSource == null)
      _collectionViewSource = intanceOfThisClass.FindResource("GroupedProfiles") as CollectionViewSource;
      _collectionViewSource?.View?.Refresh();
      }


      The OnFilterEvent method:



          private void GroupedProfiles_OnFilter(object sender, FilterEventArgs e)
      {
      e.Accepted = string.IsNullOrEmpty(FilterText) || e.Item.ToString().Contains(FilterText);
      }


      The Problem



      As you can see in the binding of the FilterText I have a delay of 5000ms. For testing purposes I've made it 5000ms instead of a reasonable 500ms.
      In order for the filter to work I need to refresh the CollectionView.
      However the PropertyChangedCallback fires immediately after each change instead of throttling it with the delay binding.



      I don't quite understand this behaviour. If this is just how a delay binding works, are there alternatives for throttling the CollectionView refresh?







      c# wpf xaml






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Nov 23 '18 at 15:16









      MartijnMartijn

      2681317




      2681317
























          1 Answer
          1






          active

          oldest

          votes


















          3














          Try reversing the bindings like this. This way the delay will be on the textbox change. Now the delay is on the filter property change (if changed from the OverviewControl).



          <TextBox x:Name="FilterTextControl" Text="{Binding ElementName=ProfileOverviewControl, Path=FilterText, Delay=5000}"/>
          <CustomControls:OverviewControl
          x:Name="ProfileOverviewControl"
          Items="{Binding AllItems}"/>





          share|improve this answer





















          • 1





            What a great idea! Very simple and does exactly what I want!

            – Martijn
            Nov 23 '18 at 16:18











          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%2f53449162%2fpropertychangedcallback-of-dependencyproperty-ignores-delay-binding%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









          3














          Try reversing the bindings like this. This way the delay will be on the textbox change. Now the delay is on the filter property change (if changed from the OverviewControl).



          <TextBox x:Name="FilterTextControl" Text="{Binding ElementName=ProfileOverviewControl, Path=FilterText, Delay=5000}"/>
          <CustomControls:OverviewControl
          x:Name="ProfileOverviewControl"
          Items="{Binding AllItems}"/>





          share|improve this answer





















          • 1





            What a great idea! Very simple and does exactly what I want!

            – Martijn
            Nov 23 '18 at 16:18
















          3














          Try reversing the bindings like this. This way the delay will be on the textbox change. Now the delay is on the filter property change (if changed from the OverviewControl).



          <TextBox x:Name="FilterTextControl" Text="{Binding ElementName=ProfileOverviewControl, Path=FilterText, Delay=5000}"/>
          <CustomControls:OverviewControl
          x:Name="ProfileOverviewControl"
          Items="{Binding AllItems}"/>





          share|improve this answer





















          • 1





            What a great idea! Very simple and does exactly what I want!

            – Martijn
            Nov 23 '18 at 16:18














          3












          3








          3







          Try reversing the bindings like this. This way the delay will be on the textbox change. Now the delay is on the filter property change (if changed from the OverviewControl).



          <TextBox x:Name="FilterTextControl" Text="{Binding ElementName=ProfileOverviewControl, Path=FilterText, Delay=5000}"/>
          <CustomControls:OverviewControl
          x:Name="ProfileOverviewControl"
          Items="{Binding AllItems}"/>





          share|improve this answer















          Try reversing the bindings like this. This way the delay will be on the textbox change. Now the delay is on the filter property change (if changed from the OverviewControl).



          <TextBox x:Name="FilterTextControl" Text="{Binding ElementName=ProfileOverviewControl, Path=FilterText, Delay=5000}"/>
          <CustomControls:OverviewControl
          x:Name="ProfileOverviewControl"
          Items="{Binding AllItems}"/>






          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Nov 23 '18 at 18:45









          Martijn

          2681317




          2681317










          answered Nov 23 '18 at 16:10









          Neil BNeil B

          9671413




          9671413








          • 1





            What a great idea! Very simple and does exactly what I want!

            – Martijn
            Nov 23 '18 at 16:18














          • 1





            What a great idea! Very simple and does exactly what I want!

            – Martijn
            Nov 23 '18 at 16:18








          1




          1





          What a great idea! Very simple and does exactly what I want!

          – Martijn
          Nov 23 '18 at 16:18





          What a great idea! Very simple and does exactly what I want!

          – Martijn
          Nov 23 '18 at 16:18


















          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%2f53449162%2fpropertychangedcallback-of-dependencyproperty-ignores-delay-binding%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

          404 Error Contact Form 7 ajax form submitting

          How to know if a Active Directory user can login interactively

          TypeError: fit_transform() missing 1 required positional argument: 'X'