Browse Source

Fix ItemsRepeater overwriting DataContext

Ported from 0e24e05dbd
pull/3424/head
Steven Kirk 6 years ago
parent
commit
0236ced64f
  1. 49
      src/Avalonia.Controls/Repeater/ViewManager.cs

49
src/Avalonia.Controls/Repeater/ViewManager.cs

@ -526,43 +526,60 @@ namespace Avalonia.Controls
return element;
}
// There are several cases handled here with respect to which element gets returned and when DataContext is modified.
//
// 1. If there is no ItemTemplate:
// 1.1 If data is an IControl -> the data is returned
// 1.2 If data is not an IControl -> a default DataTemplate is used to fetch element and DataContext is set to data
//
// 2. If there is an ItemTemplate:
// 2.1 If data is not an IControl -> Element is fetched from ElementFactory and DataContext is set to the data
// 2.2 If data is an IControl:
// 2.2.1 If Element returned by the ElementFactory is the same as the data -> Element (a.k.a. data) is returned as is
// 2.2.2 If Element returned by the ElementFactory is not the same as the data
// -> Element that is fetched from the ElementFactory is returned and
// DataContext is set to the data's DataContext (if it exists), otherwise it is set to the data itself
private IControl GetElementFromElementFactory(int index)
{
// The view generator is the provider of last resort.
var data = _owner.ItemsSourceView.GetAt(index);
var itemTemplateFactory = _owner.ItemTemplateShim;
IControl element = null;
var itemsSourceContainsElements = false;
var providedElementFactory = _owner.ItemTemplateShim;
if (itemTemplateFactory == null)
ItemTemplateWrapper GetElementFactory()
{
element = data as IControl;
if (providedElementFactory == null)
{
var factory = FuncDataTemplate.Default;
_owner.ItemTemplate = factory;
return _owner.ItemTemplateShim;
}
// No item template provided and ItemsSource contains objects derived from UIElement.
// In this case, just use the data directly as elements.
itemsSourceContainsElements = element != null;
return providedElementFactory;
}
if (element == null)
IControl GetElement()
{
if (itemTemplateFactory == null)
if (providedElementFactory == null)
{
// If no ItemTemplate was provided, use a default
var factory = FuncDataTemplate.Default;
_owner.ItemTemplate = factory;
itemTemplateFactory = _owner.ItemTemplateShim;
if (data is IControl dataAsElement)
{
return dataAsElement;
}
}
element = itemTemplateFactory.GetElement(_owner, data);
var elementFactory = GetElementFactory();
return elementFactory.GetElement(_owner, data);
}
var element = GetElement();
var virtInfo = ItemsRepeater.TryGetVirtualizationInfo(element);
if (virtInfo == null)
{
virtInfo = ItemsRepeater.CreateAndInitializeVirtualizationInfo(element);
}
if (!itemsSourceContainsElements)
if (data != element)
{
// Prepare the element
element.DataContext = data;

Loading…
Cancel
Save