0

In my UWP app I am using DynamicOverflowItemsChanging event of a CommandBar my usecase is not very complex, I tried to solve another problem I had by using this event, see the answer of this post.

So as shown in the answer in the link I provided above, I am trying to invoke this event and sync the visibility of MoreButton now the problem is this event is fired when the secondary overflow menu of command bar doesn't have the item removed or added yet, so they still show the items which they had before the event was fired, but when this event is completed then transfer of items is also completed.

So in short I want to raise another event somehow or get notified when the DynamicOverflowItemsChanging completes its execution, so I can have the correct data and set the visibility of more button correctly. or in other words I want to implement a behaviour of DynamicOverflowItemsChanged event, which unfortunately doesn't exist in the api, so I am looking for an alternative way.

I know I can invoke another event right at the end (just before DynamicOverflowItemsChanging event is finished), but that way I still don't get the correct values, correct values only become available when this event finishes its execution. Like we can do with Task.Then() so when a task completes another can automatically start, so I want something like that here . any suggestions would be appreciated.

protected override void OnApplyTemplate()
{

    var barr = (CommandBar)GetTemplateChild("MediaControlsCommandBar");

    //the event to control the dynamicoverflow automatically.
    barr.DynamicOverflowItemsChanging += (s, e) =>
    {
        if (_secondarycontrols.Items.Count == 0 && e.Action == CommandBarDynamicOverflowAction.AddingToOverflow)
            _moreButton.Visibility = Visibility.Visible;
        else if (_secondarycontrols.Items.Count == 1 && e.Action == CommandBarDynamicOverflowAction.RemovingFromOverflow)
            _moreButton.Visibility = Visibility.Collapsed;
    };//when this event finishes here I want to get notified.

    //base implementation
    base.OnApplyTemplate();
}
Martin Zikmund
  • 38,440
  • 7
  • 70
  • 91
Muhammad Touseef
  • 4,357
  • 4
  • 31
  • 75

1 Answers1

1

Warm greetings, fellow Microsoft Student Partner :-) .

The quick and dirty hack would be to add a Task.Delay to the end of the handler and hope the items will have changed until the delay is over. This is of course really ugly and error prone. I would suggest a different solution.

You already have access to the _secondarycontrols which is a CommandBarOverflowPresenter. This is very useful, because Items property has a VectorChanged event which is fired whenever an item is added, removed or changed. This means, you can actually use this event and move your logic inside it instead of using the DynamicOverflowItemsChanging event. You can then directly check for the number of items which will be accurate.

Martin Zikmund
  • 38,440
  • 7
  • 70
  • 91
  • so as soon as I get acces to my _secondarycontrols object in my control loaded event. I should subscribe to _secondarycontrols.Items.VectorChanged event? event use my logic there? @MartinZikmund – Muhammad Touseef Apr 04 '18 at 22:08
  • 1
    hhaha greetings to you too, I know you I have already followed u on GitHub a week or so ago :P – Muhammad Touseef Apr 04 '18 at 22:08
  • Yes, I would suggest attaching the `VectorChanged` right after you get access to the `_secondarycontrols` instance and then inside of the `VectorChanged` event handler put the logic that is now in the `DynamicOverflowItemsChanging` event (the `if ( _secondarycontrols.Items.Count == 0 &&` etc.) – Martin Zikmund Apr 04 '18 at 22:10
  • Cool :-) ! Nice to meet you! – Martin Zikmund Apr 04 '18 at 22:10
  • 1
    if (_secondarycontrols != null) { _secondarycontrols.Items.VectorChanged += (vs, ve) => _moreButton.Visibility = _secondarycontrols?.Items?.Count > 0 ? Visibility.Visible : Visibility.Collapsed; } This looks fine? – Muhammad Touseef Apr 04 '18 at 22:35
  • just a tip question, as far as these lambdas events are concerned, I don't need to worry about ubsubscribing to them with "-=" like normal event handlers? – Muhammad Touseef Apr 04 '18 at 22:36
  • If you subscribe the event in the class itself, it is not a problem, because when it is no longer in the UI, it will be destroyed and nothing will hold it in memory anymore. But if the event would be attached in a class that is alive for the lifetime of the app, like in App.xaml.cs, it would mean, that it would have to stay in memory forever as well, only because this particular handler belongs to a class with app lifetime – Martin Zikmund Apr 05 '18 at 05:06
  • and if somehow accidently I subscribe to same handler on same delegate instance multiple times, does that mean that same handler will execute multiple times upon invocation? or does the invocation list keeps overwritriting the old handler, if exactly same handler is subscribed again? – Muhammad Touseef Apr 05 '18 at 08:36
  • Unfortunately no, this is how events in C# work. Unless a handler is not unsubscribed, stays there and it can be even subscribed again. That is why lambda based event handlers are usually not recommended, because they cannot be unsubscribed and can sometimes lead to unwanted memory leaks. This is the case especially in Xamarin.iOS where this can easily lead to a circular dependency which the reference counting mechanism in iOS cannot resolve. – Martin Zikmund Apr 05 '18 at 08:43
  • 1
    Thanks, I had this confusion for sometime now it is clear :) – Muhammad Touseef Apr 05 '18 at 09:13
  • It is always confusing, there are many edge cases which one encounters :-D – Martin Zikmund Apr 05 '18 at 10:07
  • is there another way to do this , bcz when I use this method with independent controls ( not in mediaplayerelement ) then it works, but when I use controls in a mediaplayerelement, then it doesn't work, items get added so more button is visible and then right after that vectorchanged again invokes automatically and items are removed and button again goes collapsed :/ – Muhammad Touseef Apr 06 '18 at 20:44
  • I can confirm that it technically it works but when used with mediaplayerelement, the built in control somehow forecefuly removes all secondary items, its really disappointing bcause I cnt even find a way to override this, I want a lot of buttons hence I need the more overflow system in my controls and this is really disappointing, bcz creating my own controls totally is really error prone. – Muhammad Touseef Apr 06 '18 at 21:32
  • I can confirm it bcz I forcefuly made more button visible, and it was empty no matter wht, and with breakpoints I can see, whenever I add some secondary items, they get removed right after that. can u think of any way to achieve this or override this? – Muhammad Touseef Apr 06 '18 at 21:33