How can we get the children(calendardayitem) of parent object(calendarview) in winui? - windows

In UWP,we can fetch the children by FindDescendants<> .But in winui, we can't able to do that.
By doing with visualhelpertree,It always shows zero count in getchildCount() from the calendarview
I just wanted to know how to fetch the children of calendarview .
Also i have tried this but shows me zero child always,
private void FindDescendants1(DependencyObject parent, Type targetType)
{
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
itemchange.Text = childrenCount.ToString();
for (int i = 0; i < childrenCount; i++)
{
var child =(CalendarViewDayItem) VisualTreeHelper.GetChild(parent, i);
if (child.GetType() == targetType)
{
results.Add(child);
}
FindDescendants1(child, targetType);
}
}
Simply I have created this function to get the child and called,
foreach (DependencyObject displayedDay in results)
{
//displayedDay = (CalendarViewDayItem)displayedDay;
CalendarViewDayItem c = displayedDay as CalendarViewDayItem;
if (_highlightedDates.Contains(c.Date))
{
Console.WriteLine(c.Date.ToString());
//highlight
c.Background = new SolidColorBrush(Colors.Red);
}
itemchange.Text = c.Date.ToString();
}
But this not getting the child ,results is the list of objects here where it always show me zero .

My first guess is that you are calling FindDescendants1() before the control is loaded, in the constructor for example. If your CalendarView is in a Page, try calling FindDescendants1() in the Page's Loaded event.
But there's another problem in you code below.
var child = (CalendarViewDayItem)VisualTreeHelper.GetChild(parent, i);
You'll get an exception because you're trying to cast every DependencyObject to a CalendarViewDayItem. By removing the cast you should get the CalendarViewItems. Though, I would make the FinDescendants() static and just receive the results:
private static IEnumerable<T> FindDescendantsOfType<T>(DependencyObject parent) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is T hit)
{
yield return hit;
}
foreach (T? grandChild in FindChildrenOfType<T>(child))
{
yield return grandChild;
}
}
}
And use it like this:
this.results = FindChildrenOfType<CalendarViewDayItem>(this.CalendarViewControl);
foreach (var item in this.results)
{
// Do you work here...
}

Related

Iaccessible interface , call to accChild[] does not give child element name , accChildCount returns the count properly

I have written the below functions in C# (GetObjectByName and GetAccessibleChildren) by calling oleacc.dll. I am not able to understand when there is child of child items, it is not getting their name, i get the error "entry point not found" in accessibility.dll. Can someone help me what is happening, accChildCount gives the number correctly, but calling accChild[] doesnt give the child of child items.
IntPtr vsHandle = Process.GetProcessById(vsProcessId).MainWindowHandle;
IAccessible Paccessible = GetWindowAccessibleByHwnd(vsHandle);
IAccessible vaccessible = GetObjectByName(Paccessible, " UTF-8");
Details of the functions is below
using System.Runtime.InteropServices;
using System.Diagnostics;
using Accessibility;
[System.Runtime.InteropServices.DllImport("oleacc.dll", PreserveSig = false, CharSet = System.Runtime.InteropServices.CharSet.Auto, SetLastError = true)]
[return: System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.Interface)]
public static extern int AccessibleChildren(IAccessible paccContainer, int iChildStart, int cChildren, [Out] object[] rgvarChildren, ref int pcObtained);
public static IAccessible[] c(IAccessible accContainer)
{
// Get the number of child interfaces that belong to this object.
int childNum = 0;
try
{
childNum = accContainer.accChildCount;
Console.WriteLine("Child count is " + childNum);
}
catch (Exception ex)
{
childNum = 0;
}
// Get the child accessible objects.
IAccessible[] accObjects = new IAccessible[childNum];
int count = 0;
if (childNum != 0)
{
AccessibleChildren(accContainer, 0, childNum,
accObjects, ref count);
}
return accObjects;
}
public static IAccessible GetObjectByName(IAccessible Parent, string Name)
{
// Return null if Parent is Null or not a COM Object
if (Parent == null || !Marshal.IsComObject(Parent))
{
return null;
}
// Return the Parent if the parent matches the name
if (Parent.accName[0] != null && Parent.accName[0].Equals(Name))
{
return Parent;
}
// Recursively check the child objects
IAccessible[] children = GetAccessibleChildren(Parent);
foreach (IAccessible child in children)
{
//Console.WriteLine("Got Child as " + child.get_accName(0));
Console.WriteLine("Name" + child.accName);
IAccessible objAcc = GetObjectByName(child, Name);
if (objAcc != null) return objAcc;
}
// If we're still here then return null
return null;
}

Scroll Index method not firing consistently

In a Xamarin.Forms and Xamarin.Android project I create a Custom Render and Adapter for a ListView.
The adapter implements BaseAdapter and ISectionIndexer. The custom render of this control is using FastScroll feature, in Android when you tap this scroll a bubble with a index letter appears. This works fine, but my idea is to have a way to catch the selected index after releasing scroll and that scroll "bubble" disappears.
I thought with the following class (in the GetSectionForPosition method) could achieve that:
public class ListViewconIndexAdapter : BaseAdapter<string>, ISectionIndexer
{
string[] items;
Activity context;
string[] sections;
Java.Lang.Object[] sectionsObjects;
Dictionary<string, int> alphaIndex;
public ListViewconIndexAdapter(Activity context, string[] items) : base()
{
this.context = context;
this.items = items;
alphaIndex = new Dictionary<string, int>();
for (int i = 0; i < items.Length; i++)
{
var key = items[i][0].ToString();
if (!alphaIndex.ContainsKey(key))
alphaIndex.Add(key, i);
}
sections = new string[alphaIndex.Keys.Count];
alphaIndex.Keys.CopyTo(sections, 0);
sectionsObjects = new Java.Lang.Object[sections.Length];
for (int i = 0; i < sections.Length; i++)
{
sectionsObjects[i] = new Java.Lang.String(sections[i]);
}
}
public override Java.Lang.Object GetItem(int position)
{
return position;
}
public override long GetItemId(int position)
{
return position;
}
public override string this[int position]
{
get { return items[position]; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View view = convertView;
if (view == null)
view = context.LayoutInflater.Inflate(Android.Resource.Layout.SimpleListItem1, null);
view.FindViewById<TextView>(Android.Resource.Id.Text1).Text = items[position];
return view;
}
//Fill in cound here, currently 0
public override int Count
{
get { return items.Length; }
}
// -- ISectionIndexer --
public int GetPositionForSection(int section)
{
return alphaIndex[sections[section]];
}
public int GetSectionForPosition(int position)
{ // this method isn't called in this example, but code is provided for completeness
int prevSection = 0;
for (int i = 0; i < sections.Length; i++)
{
if (GetPositionForSection(i) > position)
{
break;
}
prevSection = i;
}
Console.WriteLine(prevSection);
Console.WriteLine(sections[prevSection]);
//Toast.MakeText(context, sections[prevSection], ToastLength.Short).Show();
Xamarin.Forms.MessagingCenter.Send<object,string>(this, "CambioSeccion", sections[prevSection]);
return prevSection;
}
}
I put those Console.writeline for checking the index letter and that Message send is a way to send it back to PCL/NET Standard code (to show an DisplayAlert or something).
But the problem is that method firing is not consistent, for example, sometimes you fast scroll down to 'C' but Console doesn't print anything after releasing it there, but after touching it again where you leave it, it fires up. But sometimes it works like i want, it prints after release the scroll at selected index.
ListView has two different scroll listeners, AbsListView.IOnScrollListener and AbsListView.IOnScrollChangeListener (this one was added in API 23) and a touch listener (AbsListView.IOnTouchListener)
I think based upon your use-case, you are looking for the OnScrollStateChanged and when it goes into idle state and you are not touching the listview, do something (or vice versa).
Example (adjust to your needs of course):
public class MyScrollListener : Java.Lang.Object, AbsListView.IOnTouchListener, AbsListView.IOnScrollListener, AbsListView.IOnScrollChangeListener //(API23)
{
bool touching;
bool scrolling;
public void OnScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount)
{
}
public void OnScrollChange(View v, int scrollX, int scrollY, int oldScrollX, int oldScrollY)
{
}
public void OnScrollStateChanged(AbsListView view, [GeneratedEnum] ScrollState scrollState)
{
switch(scrollState)
{
case ScrollState.Idle:
if (!touching)
{
scrolling = false;
GetSelection();
}
break;
default:
scrolling = true;
break;
}
}
public bool OnTouch(View v, MotionEvent e)
{
switch (e.Action)
{
case MotionEventActions.Up:
touching = false;
if (!scrolling)
GetSelection();
break;
default:
touching = true;
break;
}
return true;
}
void GetSelection()
{
// touch and srolling is done, do something
}
}
Usage:
var scrollListener = new MyScrollListener();
listView.SetOnTouchListener(scrollListener);
listView.SetOnScrollListener(scrollListener);
listView.SetOnScrollChangeListener(scrollListener); // API23

Null Reference Exception with ListViewItem

I have the following code:
class Album
{
private string name;
private Music[] musics;
private const int MAX_MUSICS = 100;
private ListViewItem[] back;
public ListViewItem[] GetTitles()
{
for (int i = 0; i < MAX_MUSICS; i++)
if (musics[i].Title != null)
back[i] = new ListViewItem(musics[i].Title);
return back;
}
}
At the line back[i] = new ListViewItem(musics[i].Title), I get a NullReferenceException.
I dont know why because in the debuger musics[i].Title has a value and its even checked.
You need to tell how many elements 'back' array will have before you enter elements to it e.g.
public ListViewItem[] GetTitles()
{
back = new ListViewItem[MAX_MUSICS]; // initialize array
for (int i = 0; i < MAX_MUSICS; i++)
if (musics[i].Title != null)
back[i] = new ListViewItem(musics[i].Title);
return back;
}
Also make sure that your MAX_MUSICS is not bigger than size of musics array, otherwise you will hit into another exception

WP7 find control inside header of pivotitem

For my WP7 app, I need to find a date control which I have placed in the header template of the pivotitem.
How do I access this datepicker control in the code behind for the currently selected PivotItem?
public static T FindName<T>(string name, DependencyObject reference) where T : FrameworkElement
{
if (string.IsNullOrEmpty(name))
{
throw new ArgumentNullException("name");
}
if (reference == null)
{
throw new ArgumentNullException("reference");
}
return FindNameInternal<T>(name, reference);
}
private static T FindNameInternal<T>(string name, DependencyObject reference) where T : FrameworkElement
{
foreach (DependencyObject obj in GetChildren(reference))
{
T elem = obj as T;
if (elem != null && elem.Name == name)
{
return elem;
}
elem = FindNameInternal<T>(name, obj);
if (elem != null)
{
return elem;
}
else
{
//if (obj.GetType().FullName == "System.Windows.Controls.DataField")
// elem = (obj as DataField).Content as T;
if (elem != null && elem.Name == name)
return elem;
}
}
return null;
}
private static IEnumerable<DependencyObject> GetChildren(DependencyObject reference)
{
int childCount = VisualTreeHelper.GetChildrenCount(reference);
if (childCount > 0)
{
for (int i = 0; i < childCount; i++)
{
yield return VisualTreeHelper.GetChild(reference, i);
}
}
}
I don't know of any real good solution to this. I guess my initial thought was why do you need a reference to the DatePicker object? But I guess you have your reasons.
A possible solution though:
You could use the VisualTreeHelper to traverse the visual tree from your pivot item and stop when you find an object of the correct type (DatePicker). Create a helper function like this:
private static DependencyObject GetDependencyObjectFromVisualTree(DependencyObject startObject, Type type)
{
DependencyObject parent = startObject;
while (parent != null)
{
if (type.IsInstanceOfType(parent))
break;
parent = VisualTreeHelper.GetParent(parent);
}
return parent;
}
Then call it with the PivotItem as the DependencyObject, typeof(DatePicker) as the type and finally cast the returned DependencyObject to a DatePicker.
HTH
The regular Parent/Child relationship doesn't really work for the Pivot control. What you can do is search for the DatePicked component directly in the PivotItem:
((DatePicker)((PivotItem)MainPivot.SelectedItem).FindName("DateControl"))
MainPivot is the Pivot control. I am getting the currently selected item via SelectedItem - notice that I am casting it to PivotItem directly, since otherwise I get an object. Then I am looking for a control named DateControl, given that you have a x:Name set for it.
All that needs to be done after that is cast the object to DatePicker and access its properties the same way you would do for any other control.

Blackberry - get checked items from list with checkboxes

How can all checked items from a list can be fetched?
I need to get all selected (checked) items from the list and populate a vector.
I am not getting all selected items, I am getting only the item on which current focus is.
I am implementing listfield with checkboxes as per the knowledgebase article.
If I use getSelection(), it is returning me the currently highlighted list row index, and not all that have been checked.
As I undestood, sample is How To - Create a ListField with check boxes
Then you can add Vector to the class where ListFieldCallback is implemented:
private Vector _checkedData = new Vector();
public Vector getCheckedItems() {
return _checkedData;
}
and update drawListRow this way:
if (currentRow.isChecked())
{
if( -1 ==_checkedData.indexOf(currentRow))
_checkedData.addElement(currentRow);
rowString.append(Characters.BALLOT_BOX_WITH_CHECK);
}
else
{
if( -1 !=_checkedData.indexOf(currentRow))
_checkedData.removeElement(currentRow);
rowString.append(Characters.BALLOT_BOX);
}
If you would use VerticalFieldManager with custom CheckBoxField, you could iterate over all fields on screen (or any manager) and check if its' checkbox field, then take a value:
class List extends VerticalFieldManager {
...
public Vector getCheckedItems() {
Vector result = new Vector();
for (int i = 0, cnt = getFieldCount(); i < cnt; i++) {
Field field = getField(i);
if (field instanceof CheckboxField) {
CheckboxField checkboxField = (CheckboxField) field;
if (checkboxField.isChecked())
result.addElement(checkboxField);
}
}
return result;
}
}
#sandhya-m
class List extends VerticalFieldManager {
...
public void selectAll() {
for (int i = 0, cnt = getFieldCount(); i < cnt; i++) {
Field field = getField(i);
if (field instanceof CheckboxField) {
CheckboxField checkboxField = (CheckboxField) field;
checkboxField.setChecked(true);
}
}
}
}

Resources