我需要在我的 xamarin 表单应用程序中使用 Treeview,但是网络上唯一现有的 TreeView 不是免费的(Syncfusion 和 Telerik)。
所以我发现了这个非常有趣的项目:https ://github.com/AdaptSolutions/Xamarin.Forms-TreeView
我发现的唯一问题是 ItemSource 和 SelectedItem 属性不可绑定,因此我不能在 MVVM 模式上使用它。这给我们带来了我的问题,我怎样才能使它们可绑定。
我尝试遵循此文档:https ://docs.microsoft.com/en-us/xamarin/xamarin-forms/xaml/bindable-properties
但仍然没有。任何人都可以帮我吗?谢谢
更新 :
这是 TreeView 类:
public class TreeView : ScrollView
{
#region Fields
private readonly StackLayout _StackLayout = new StackLayout { Orientation = StackOrientation.Vertical };
//TODO: This initialises the list, but there is nothing listening to INotifyCollectionChanged so no nodes will get rendered
private IList<TreeViewNode> _RootNodes = new ObservableCollection<TreeViewNode>();
private TreeViewNode _SelectedItem;
#endregion
#region Public Properties
public TreeViewNode SelectedItem
{
get => _SelectedItem;
set
{
if (_SelectedItem == value)
{
return;
}
if (_SelectedItem != null)
{
_SelectedItem.IsSelected = false;
}
_SelectedItem = value;
SelectedItemChanged?.Invoke(this, new EventArgs());
}
}
public IList<TreeViewNode> RootNodes
{
get => _RootNodes;
set
{
_RootNodes = value;
if (value is INotifyCollectionChanged notifyCollectionChanged)
{
notifyCollectionChanged.CollectionChanged += (s, e) =>
{
RenderNodes(_RootNodes, _StackLayout, e, null);
};
}
RenderNodes(_RootNodes, _StackLayout, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset), null);
}
}
#endregion
#region Constructor
public TreeView()
{
Content = _StackLayout;
}
#endregion
#region Private Static Methods
private static void AddItems(IEnumerable<TreeViewNode> childTreeViewItems, StackLayout parent, TreeViewNode parentTreeViewItem)
{
foreach (var childTreeNode in childTreeViewItems)
{
if (!parent.Children.Contains(childTreeNode))
{
parent.Children.Add(childTreeNode);
}
childTreeNode.ParentTreeViewItem = parentTreeViewItem;
}
}
#endregion
#region Internal Static Methods
internal static void RenderNodes(IEnumerable<TreeViewNode> childTreeViewItems, StackLayout parent, NotifyCollectionChangedEventArgs e, TreeViewNode parentTreeViewItem)
{
if (e.Action != NotifyCollectionChangedAction.Add)
{
AddItems(childTreeViewItems, parent, parentTreeViewItem);
}
else
{
AddItems(e.NewItems.Cast<TreeViewNode>(), parent, parentTreeViewItem);
}
}
#endregion
}
所以我在这里尝试做的是使 RootNodes 以及之后的 SelectedItem 可绑定。
我所做的只是添加这个,认为它应该可以工作,但显然它没有:
public static readonly BindableProperty RootNodesProperty =
BindableProperty.Create(nameof(RootNodes), typeof(IList<TreeViewNode>), typeof(TreeView));
public IList<TreeViewNode> RootNodes
{
get => (IList<TreeViewNode>)GetValue(RootNodesProperty);
set
{
SetValue(RootNodesProperty, value);
_RootNodes = value;
if (value is INotifyCollectionChanged notifyCollectionChanged)
{
notifyCollectionChanged.CollectionChanged += (s, e) =>
{
RenderNodes(_RootNodes, _StackLayout, e, null);
};
}
RenderNodes(_RootNodes, _StackLayout, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset), null);
}
}
希望这可以帮助