0

I am developing UWP Win10 VS2015 App. I have customized the Calendar Control but need to implement the following features.

  1. Tap on any date, it should highlight with round filled circle.

  2. Tap and Slide finger on multiple dates, it should Select that Range of Dates.

Is there any Visualstates or other Events to put inside the Style (ControlTemplate) and manipulate it to slide finger and when hit boundary of another date it should highlight. ??? Or what procedure should be applied here :)

See the following 4 Screen Shots. (these are just sample shots and I need such type of functionality)

enter image description here

enter image description here

enter image description here

enter image description here

According to the above screen shots ... this is a custom feature I think, and the Style and template may be edited and some Manipulation, Tap and Drag events may be put inside the style ... but how to put these and atleast get idea of putting this feature ... it will be much appreciated. thanks.


Updated

enter image description here

See the animated pic, and compare it with other figures as given at top ... When we click on any item the background of Border should become BLUE and the Text i.e. Date should become WHITE as shown in the above figures. Actually there is no ContentPresenter OR ItemPresenter inside the CalendarviewDayItem Style ... so plz put this feature. Thanks.


Alhamdulillah we are very close to our target now ... and InshaAllah can put the "Range Selection" feature, so I want to refer you to some topics which definitely help us in "Multi Selection" feature. :)

HitTest via VisualTreeHelper

VisualTreeHelper.FindElementsInHostCoordinates(Point, UIElement) method

UIElement.FindSubElementsForTouchTargeting method

Physics Helper XAML

XAML Collision detection

Xaml Behavior SDK

So, if you check these topics. You will get help to implement the Multi Selection feature on finger swipe InshaAllah :)

Community
  • 1
  • 1
Zia Ur Rahman
  • 1,850
  • 1
  • 21
  • 30
  • However i can olny give half answer. Regarding making day item round filled circle on tap. Please refer these links https://social.msdn.microsoft.com/Forums/windowsapps/en-US/d49e5a38-840c-45cd-80c9-27828eaf8736/uwp-xaml-calendarview-item-background-style?forum=wpdevelop – Archana Mar 21 '16 at 11:43
  • and this one https://social.msdn.microsoft.com/Forums/en-US/060177b4-5ff2-409c-816f-2e91b0e97474/uwpxamlcustomize-calendarview-item-background-style?forum=wpdevelop. They are telling you can use CalendarViewDayItemChanging event to change the style of the item when the item is tapped – Archana Mar 21 '16 at 11:45
  • Thanks @Archana, I already have read such posts ... And the 1st portion is actually I put as a part of the 2nd question ... otherwise I already have handled this via code behind. Now I need the 2nd question, so please do some favor for that ... I am trying too, and if got it then will share it and will inform u. Thanks :) – Zia Ur Rahman Mar 21 '16 at 15:44
  • @Archana, Just like you have done in my previous questions in SelectionChange event, triggered the Custom VisualStates. Here in Calendar Control an event SelectedDatesChanged is available and also have args.AddedDates and args.Removes, so how can I get the currently clicked and previously clicked date and Run a VisualStateManager.GoToState ............. plz. – Zia Ur Rahman Mar 22 '16 at 04:19
  • Actually I have problem in getting the SelectedDate but there is no command of ContainerFromItem, so how can I get the current and previous ContainterFrmItem – Zia Ur Rahman Mar 22 '16 at 04:31
  • Do you want to fetch selected CalendarViewDayItem? – Archana Mar 22 '16 at 05:10
  • If so you can use VisualTreeHelper for that – Archana Mar 22 '16 at 06:00
  • And the selected day Item can be fetched via CalendarViewDayItemChanging event, wherein args.Item.Date and other properties we can get data. I have actually put a Border Control having CornorRadius = 100 in the CalendarDayItem Style, so it become a Circle Filled with blue color, but now want that when I click on any Item it shows like figure-1 (as in screenshot) and when click another the previous one become white (transparent) and the current one filled with blue circle. – Zia Ur Rahman Mar 22 '16 at 06:06
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/106978/discussion-between-archana-and-zia-ur-rahman). – Archana Mar 22 '16 at 06:26
  • I ll post the code for that. – Archana Mar 22 '16 at 06:29

1 Answers1

1

Xaml style for calendarViewDayItem

<Style x:Key="CalendarViewDayItemStyle1" TargetType="CalendarViewDayItem">
            <Setter Property="MinWidth" Value="40"/>
            <Setter Property="MinHeight" Value="40"/>
            <Setter Property="Margin" Value="1"/>
            <Setter Property="Padding" Value="0, 0, 0, 4"/>
            <Setter Property="BorderThickness" Value="0"/>

            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="CalendarViewDayItem">
                        <Grid >
                            <VisualStateManager.VisualStateGroups>
                                <VisualStateGroup x:Name="CustomStates">
                                    <VisualState x:Name="Hover">
                                        <VisualState.Setters>
                                            <Setter Target="ContentPresenter.(Border.Background)" Value="Blue"/>
                                        </VisualState.Setters>
                                    </VisualState>
                                    <VisualState x:Name="Normal">
                                        <VisualState.Setters>
                                            <Setter Target="ContentPresenter.(Border.Background)" Value="White"/>
                                        </VisualState.Setters>
                                    </VisualState>
                                </VisualStateGroup>
                            </VisualStateManager.VisualStateGroups>
                            <Border x:Name="ContentPresenter" PointerPressed="border_PointerPressed"  PointerEntered="border_PointerEntered" BorderBrush="Red" PointerExited="border_PointerExited" PointerMoved="border_PointerMoved" BorderThickness="1,1,1,1" CornerRadius="10,10,10,10" >

                            </Border>
                        </Grid>

                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

Code Behind

     CalendarViewDayItem item;
                private void CalendarView_CalendarViewDayItemChanging(CalendarView sender, CalendarViewDayItemChangingEventArgs args)
                {
                    var item = args.Item;

                    item.PointerPressed += Item_PointerPressed;
                    item.Tapped += Item_Tapped;
                    item.PointerEntered += Item_PointerEntered;
                    item.PointerExited += Item_PointerExited;

                }
         private void Item_PointerExited(object sender, PointerRoutedEventArgs e)
        {
            item = null;
        }
                private void Item_PointerEntered(object sender, PointerRoutedEventArgs e)
                {
                    item = sender as CalendarViewDayItem;
                }


                private void Item_Tapped(object sender, TappedRoutedEventArgs e)
                {
                    item = sender as CalendarViewDayItem;
                    (sender as CalendarViewDayItem).Background = new SolidColorBrush(Colors.Red);
                }

                private void Item_PointerPressed(object sender, PointerRoutedEventArgs e)
                {
                    item = sender as CalendarViewDayItem;

                }

                private void border_PointerEntered(object sender, PointerRoutedEventArgs e)
                {
                    if (item != null)
                    {
                        VisualStateManager.GoToState((item), "Hover", true);
                    }
                }

                private void border_PointerMoved(object sender, PointerRoutedEventArgs e)
                {
                    if (item != null)
                    {
                        VisualStateManager.GoToState((item), "Hover", true);
                    }
                }

                private void border_PointerExited(object sender, PointerRoutedEventArgs e)
                {
                    if (item != null)
                    {
                        VisualStateManager.GoToState((item), "Normal", true);
                    }
                }            
                private void border_PointerPressed(object sender, PointerRoutedEventArgs e)
                {
                    if (item != null)
                    {
                        VisualStateManager.GoToState((item), "Hover", true);
                    }


}

Update

Just use below methods to make selected one to blue. Remove above code behind codes

    private void CalendarView_SelectedDatesChanged(CalendarView sender, CalendarViewSelectedDatesChangedEventArgs args)
            {
                if(args.AddedDates!=null)
                {
                    foreach(var item in args.AddedDates)
                    {
                      var selected =  FindElementInVisualTree<CalendarViewDayItem>(sender, item);
                    }
                }
                if (args.RemovedDates != null)
                {
                    foreach (var item in args.RemovedDates)
                    {

                    }
                }
            }
            public static T FindElementInVisualTree<T>(DependencyObject parentElement,DateTimeOffset selectedDate) where T : DependencyObject
            {
                var count = VisualTreeHelper.GetChildrenCount(parentElement);
                if (count == 0) return null;

                for (int i = 0; i < count; i++)
                {
                    var child = VisualTreeHelper.GetChild(parentElement, i);

                    if (child != null && child is CalendarViewDayItem)
                    {
                       if((child as CalendarViewDayItem).Date==selectedDate.DateTime)
                        {
                            VisualStateManager.GoToState((child as CalendarViewDayItem), "Hover", true);
                        }
 else if ((child as CalendarViewDayItem).Date.Date == DateTime.Today)
                    {
                       // VisualStateManager.GoToState((child as CalendarViewDayItem), "Hover", true);
//styles for today's date
                    }
                       else
                        {
                            VisualStateManager.GoToState((child as CalendarViewDayItem), "Normal", true);
                        }
                    }
                    else
                    {
                        var result = FindElementInVisualTree<T>(child,selectedDate);
                        if (result != null)
                            return result;
                    }
                }
                return null;
            }

When we click on any item the background of Border should become BLUE and the Text i.e. Date should become WHITE as shown in the above figures

There are lot of properties for calendar control. Search for this PressedForeground and change the value of it to white and go through other similar properties also

Archana
  • 3,213
  • 1
  • 15
  • 21
  • Thanks for your interest. This is good approach and you have done well. But actually this behave on PointerOver and PointerExit, and doesn't work on PointerPressed which will remain the Blue color on the Selected Date and when click another item then the previous one should be white and current one should be Blue. And more over, If we put the Setter Property Horizontal and value to Center and remove the Padding value, and also Remove this Border "ContentPresenter" control, then the DayItems will be aligned center but when put the Border Control it align to Left ... Plz check this too – Zia Ur Rahman Mar 22 '16 at 16:43
  • OK, Leave the 2nd Prob. i.e. Aligning Center ... It has been set, but please give me at-least an idea that If I Tap a DayItem and then move/slide my finger toward other DayItem then which event should be fired which detect the other boundary of Dayitem and Add them to a Queue/List Collection. – Zia Ur Rahman Mar 22 '16 at 17:04
  • You can achieve that in SelectedDatesChanged event of CalendarView. Please see my updated answer – Archana Mar 23 '16 at 05:23
  • In removed dates you can get previously selected item. You can add it to queue. Let me know if that helps. I have posted VisualTreeHelper code to get the day item. – Archana Mar 23 '16 at 05:30
  • Thank you so much. Definitely it helped me alot. I have implemented it and it worked and almost my 1st Part is completed. I have updated my question and put an animated Gif to show you the work Thanks. You plz check the "UPDATED" portion at the end of my Question and please read the Links/Topics... InshaAllah it will help us to get the Multi-Selection on Finger Swipe, because most of the topics have VisualTreeHelper class implemented. Plz help for this. Thanks. – Zia Ur Rahman Mar 23 '16 at 09:37
  • Did you able to solve the problem? If so please post the code. It will help others. I have checked all the links but couldn't find the solution – Archana Mar 24 '16 at 13:54
  • No, not yet ... I am creating my own Custom Calendar Control with the help of Delegation and Decorator Design Pattern ... It have much work to do but InshaAllah will get it soon. :) then for demo purpose, may be I share the .gif and may be some code if needed. Manipulation events are not used for this purpose ... it only detect the Control/Object to Translate/Rotate/Scale which has the Touch Interception ... this type of work is actually be done via MouseDown/MouseUp/MouseEnter/MouseExit events etc.... which get the HitTesting of object. – Zia Ur Rahman Mar 24 '16 at 15:22
  • @LovetoCode Default view of selected date is Square , how to change it to circle and how to change the selected date background, I was able to customize `SelectedBorderBrush` but that just changed the border. – Kinjan Bhavsar Jun 24 '16 at 06:13
  • Give CornerRadius="10,10,10,10" to border – Archana Jun 24 '16 at 06:17