Showing posts with label ItemControl. Show all posts
Showing posts with label ItemControl. Show all posts

Thursday, June 5, 2008

Correct use ItemsSource in WPF for controls inherited from ItemsControl

Use NET.ReflectorI sometimes read MSDN forums of WPF. I have founded post with interesting problem. I was interested this trouble.

We can download sample from there. Pay attention that ListView have strange behavior: pressing "s" moves the focus to the next item. I was interested this problem and little investigate it. This action relations with search functionality. If we don't need search functionality we can easy fix it, override ToString() method:

public override string ToString()
{
return string.Empty;
}

FYI:
If you need more details why does it do, you can read next:

After you type letter 's', next methods were called:
...................
- void OnTextInput( TextCompositionEventArgs e ) of ItemsControl;
- bool DoSearch(string nextChar) of TextSearch;
- int FindMatchingPrefix(ItemsControl itemsControl, string primaryTextPath, string prefix, string newChar, int startItemIndex, bool lookForFallbackMatchToo, ref bool wasNewCharUsed) of TextSearch;

- string GetPrimaryText(object item, BindingExpression primaryTextBinding, DependencyObject primaryTextBindingHome) of TextSearch
private static string GetPrimaryText(object item, BindingExpression primaryTextBinding, DependencyObject primaryTextBindingHome)
{
//item is EmployeeInfo (!!)
DependencyObject obj2 = item as DependencyObject;

if (obj2 != null) // false
{
string str = (string) obj2.GetValue(TextProperty);
if (!string.IsNullOrEmpty(str))
{
return str;
}
}
if ((primaryTextBinding != null) && (primaryTextBindingHome != null)) //false
{
primaryTextBinding.Activate(item);
return ConvertToPlainText(primaryTextBinding.Value);
}
return ConvertToPlainText(item); //It was called
}

-string ConvertToPlainText(object o) of TextSearch
private static string ConvertToPlainText(object o)
{
FrameworkElement element = o as FrameworkElement;
if (element != null) //false
{
string plainText = element.GetPlainText();
if (plainText != null)
{
return plainText;
}
}
if (o == null) // false
{
return string.Empty;
}
return o.ToString(); //return "SDKSample.EmployeeInfo"
}


- In this FindMatchingPrefix method we prepare this string as follows
........................
string str2 = GetPrimaryText(obj3, bindingExpr, itemsControl);
if ((str2 != null) && str2.StartsWith(str, true, culture)) //"SDKSample.EmployeeInfo" is started with "s" ;) (!!!!!)
{
wasNewCharUsed = true;
num = num4;
break;
}
........................
return num;


- and in the DoSearch(string nextChar) method
........................
int itemIndex = FindMatchingPrefix(this._attachedTo, primaryTextPath, this.Prefix, nextChar, startItemIndex, lookForFallbackMatchToo, ref wasNewCharUsed);

if (itemIndex != -1)
{
if (!this.IsActive || (itemIndex != startItemIndex))
{
object item = items[itemIndex];

this._attachedTo.NavigateToItem(item, itemIndex, new ItemsControl.ItemNavigateArgs(Keyboard.PrimaryDevice, ModifierKeys.None)); //wrong code is started
this.MatchedItemIndex = itemIndex;
}

........................

Nothing is perfect..

Sunday, April 13, 2008

ItemsSource tips & tricks

Describe problem.

When we wish to implement the mechanism Drag&Drop of Children for our control in WPF, particularly that our control contains children in its logical tree (in other case attached and inherit properties work incorrect sometimes). Let that control template contains some other controls inherit from ItemControl. We wish add some children to this inherit from ItemControl controls. What can we do?

If we use Items that we have a disagreeable surprise - we should add items to logical tree of internal control (previous to remove from our control's logical tree - it is the problem described above). But we can create collection inherit of IEnumerable and it is bound to ItemsSource of internal controls - all will be worked nice.

Note:

If property ItemsSource isn't equal 'null' that we can work with Items in read-only mode. If ItemsSource equal 'null' that we can full use Items (It is empty after those actions). If we need dynamic change of items we can implement INotifyPropertyChanged interface. The better solution is to use ObservableCollection for this purpose.