mirror of
https://github.com/AtomUI/AtomUI.git
synced 2026-10-22 00:46:48 +08:00
Refactor treeview
add ToggleType support
This commit is contained in:
@@ -151,6 +151,10 @@ internal class DataGridFilterIndicator : IconButton
|
||||
Placement = PlacementMode.BottomEdgeAlignedRight,
|
||||
IsDetectMouseClickEnabled = false
|
||||
};
|
||||
BindUtils.RelayBind(this, FilterMultipleProperty, treeFlyout, DataGridTreeFilterFlyout.ToggleTypeProperty, (v) =>
|
||||
{
|
||||
return v ? ItemToggleType.CheckBox : ItemToggleType.Radio;
|
||||
});
|
||||
BindUtils.RelayBind(owningGrid, MotionAwareControlProperty.IsMotionEnabledProperty, treeFlyout,
|
||||
MotionAwareControlProperty.IsMotionEnabledProperty);
|
||||
var selectAllTreeItem = new DataGridFilterTreeItem();
|
||||
@@ -208,7 +212,7 @@ internal class DataGridFilterIndicator : IconButton
|
||||
Header = item.Text,
|
||||
FilterValue = item.Value
|
||||
};
|
||||
// BindUtils.RelayBind(this, ToggleTypeProperty, treeItem, TreeViewItem.ToggleTypeProperty);
|
||||
|
||||
treeItems.Add(treeItem);
|
||||
if (item.Children.Count > 0)
|
||||
{
|
||||
|
||||
@@ -1,13 +1,22 @@
|
||||
using AtomUI.Data;
|
||||
using AtomUI.MotionScene;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Metadata;
|
||||
|
||||
namespace AtomUI.Controls;
|
||||
|
||||
internal class DataGridTreeFilterFlyout : TreeViewFlyout
|
||||
{
|
||||
internal static readonly StyledProperty<ItemToggleType> ToggleTypeProperty =
|
||||
TreeView.ToggleTypeProperty.AddOwner<DataGridTreeFilterFlyout>();
|
||||
|
||||
public ItemToggleType ToggleType
|
||||
{
|
||||
get => GetValue(ToggleTypeProperty);
|
||||
set => SetValue(ToggleTypeProperty, value);
|
||||
}
|
||||
|
||||
public event EventHandler<DataGridFilterValuesSelectedEventArgs>? FilterValuesSelected;
|
||||
|
||||
public DataGridTreeFilterFlyout()
|
||||
@@ -21,11 +30,11 @@ internal class DataGridTreeFilterFlyout : TreeViewFlyout
|
||||
var presenter = new DataGridTreeFilterFlyoutPresenter
|
||||
{
|
||||
IsDefaultExpandAll = true,
|
||||
ItemsSource = Items,
|
||||
IsCheckable = true
|
||||
ItemsSource = Items
|
||||
};
|
||||
BindUtils.RelayBind(this, IsShowArrowEffectiveProperty, presenter, MenuFlyoutPresenter.IsShowArrowProperty);
|
||||
BindUtils.RelayBind(this, IsMotionEnabledProperty, presenter, MenuFlyoutPresenter.IsMotionEnabledProperty);
|
||||
BindUtils.RelayBind(this, IsShowArrowEffectiveProperty, presenter, DataGridTreeFilterFlyoutPresenter.IsShowArrowProperty);
|
||||
BindUtils.RelayBind(this, IsMotionEnabledProperty, presenter, DataGridTreeFilterFlyoutPresenter.IsMotionEnabledProperty);
|
||||
BindUtils.RelayBind(this, ToggleTypeProperty, presenter, DataGridTreeFilterFlyoutPresenter.ToggleTypeProperty);
|
||||
return presenter;
|
||||
}
|
||||
|
||||
@@ -39,18 +48,6 @@ internal class DataGridTreeFilterFlyout : TreeViewFlyout
|
||||
internal class DataGridFilterTreeItem : TreeViewItem
|
||||
{
|
||||
public string? FilterValue { get; set; }
|
||||
|
||||
protected override void NotifyHeaderClick()
|
||||
{
|
||||
if (IsChecked is null)
|
||||
{
|
||||
IsChecked = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsChecked = !IsChecked;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnHeaderDoubleTapped(TappedEventArgs e)
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
xmlns:atom="https://atomui.net"
|
||||
x:Class="AtomUI.Controls.Themes.TreeViewItemTheme">
|
||||
<Setter Property="Template">
|
||||
<ControlTemplate>
|
||||
<ControlTemplate TargetType="atom:TreeViewItem">
|
||||
<StackPanel Orientation="Vertical">
|
||||
<Border Name="{x:Static atom:TreeViewItemThemeConstants.FramePart}"
|
||||
Focusable="True"
|
||||
@@ -24,12 +24,22 @@
|
||||
LeafIcon="{TemplateBinding SwitcherLeafIcon}"
|
||||
IsChecked="{TemplateBinding IsExpanded, Mode=TwoWay}"
|
||||
IsLoading="{TemplateBinding IsLoading}" />
|
||||
<atom:CheckBox HorizontalAlignment="Left"
|
||||
|
||||
<atom:CheckBox Name="{x:Static atom:TreeViewItemThemeConstants.ToggleCheckboxPart}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Grid.Column="1"
|
||||
IsVisible="{TemplateBinding IsCheckboxVisible}"
|
||||
IsEnabled="{TemplateBinding IsCheckboxEnable}"
|
||||
IsChecked="{TemplateBinding IsChecked, Mode=TwoWay}" />
|
||||
IsChecked="{TemplateBinding IsChecked}"
|
||||
IsEnabled="{TemplateBinding IsEnabled}"
|
||||
IsVisible="False" />
|
||||
<atom:RadioButton Name="{x:Static atom:TreeViewItemThemeConstants.ToggleRadioPart}"
|
||||
HorizontalAlignment="Left"
|
||||
VerticalAlignment="Center"
|
||||
Grid.Column="1"
|
||||
IsChecked="{TemplateBinding IsChecked}"
|
||||
GroupName="{TemplateBinding GroupName}"
|
||||
IsVisible="False" />
|
||||
|
||||
<atom:IconPresenter Name="{x:Static atom:TreeViewItemThemeConstants.IconPresenterPart}"
|
||||
Grid.Column="2"
|
||||
Icon="{TemplateBinding Icon}"
|
||||
@@ -101,6 +111,19 @@
|
||||
<Setter Property="EffectiveNodeBg"
|
||||
Value="{DynamicResource {x:Static atom:TreeViewTokenKey.NodeSelectedBg}}" />
|
||||
</Style>
|
||||
|
||||
<Style Selector="^[ToggleType=CheckBox]">
|
||||
<Style Selector="^ /template/ atom|CheckBox#PART_ToggleCheckbox">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^[ToggleType=Radio]">
|
||||
<Style Selector="^ /template/ atom|RadioButton#PART_ToggleRadio">
|
||||
<Setter Property="IsVisible" Value="True" />
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<!-- BuildCommonStyle 结束 -->
|
||||
<!-- BuildSwitcherButtonStyle 开始 -->
|
||||
|
||||
@@ -122,7 +145,7 @@
|
||||
</Style>
|
||||
</Style>
|
||||
|
||||
<Style Selector="^[IsCheckboxVisible=True]">
|
||||
<Style Selector="^[ToggleType=CheckBox], ^[ToggleType=Radio]">
|
||||
<Style Selector="^ /template/ atom|NodeSwitcherButton#PART_NodeSwitcherButton">
|
||||
<Setter Property="Margin"
|
||||
Value="{DynamicResource {x:Static atom:TreeViewTokenKey.TreeNodeSwitcherMargin}}" />
|
||||
|
||||
@@ -9,6 +9,8 @@ internal static class TreeViewItemThemeConstants
|
||||
public const string HeaderPresenterPart = "PART_HeaderPresenter";
|
||||
public const string IconPresenterPart = "PART_IconPresenter";
|
||||
public const string NodeSwitcherButtonPart = "PART_NodeSwitcherButton";
|
||||
public const string ToggleCheckboxPart = "PART_ToggleCheckbox";
|
||||
public const string ToggleRadioPart = "PART_ToggleRadio";
|
||||
}
|
||||
|
||||
internal static class NodeSwitcherButtonThemeConstants
|
||||
|
||||
@@ -35,9 +35,6 @@ public class TreeView : AvaloniaTreeView,
|
||||
public static readonly StyledProperty<bool> IsDraggableProperty =
|
||||
AvaloniaProperty.Register<TreeView, bool>(nameof(IsDraggable));
|
||||
|
||||
public static readonly StyledProperty<bool> IsCheckableProperty =
|
||||
AvaloniaProperty.Register<TreeView, bool>(nameof(IsCheckable));
|
||||
|
||||
public static readonly StyledProperty<bool> IsShowIconProperty =
|
||||
AvaloniaProperty.Register<TreeView, bool>(nameof(IsShowIcon));
|
||||
|
||||
@@ -61,19 +58,16 @@ public class TreeView : AvaloniaTreeView,
|
||||
|
||||
public static readonly StyledProperty<AbstractMotion?> CloseMotionProperty =
|
||||
Popup.CloseMotionProperty.AddOwner<TreeView>();
|
||||
|
||||
public static readonly StyledProperty<ItemToggleType> ToggleTypeProperty =
|
||||
AvaloniaProperty.Register<TreeView, ItemToggleType>(nameof(ToggleType), ItemToggleType.None);
|
||||
|
||||
public bool IsDraggable
|
||||
{
|
||||
get => GetValue(IsDraggableProperty);
|
||||
set => SetValue(IsDraggableProperty, value);
|
||||
}
|
||||
|
||||
public bool IsCheckable
|
||||
{
|
||||
get => GetValue(IsCheckableProperty);
|
||||
set => SetValue(IsCheckableProperty, value);
|
||||
}
|
||||
|
||||
|
||||
public bool IsShowIcon
|
||||
{
|
||||
get => GetValue(IsShowIconProperty);
|
||||
@@ -122,6 +116,12 @@ public class TreeView : AvaloniaTreeView,
|
||||
set => SetValue(CloseMotionProperty, value);
|
||||
}
|
||||
|
||||
public ItemToggleType ToggleType
|
||||
{
|
||||
get => GetValue(ToggleTypeProperty);
|
||||
set => SetValue(ToggleTypeProperty, value);
|
||||
}
|
||||
|
||||
public bool IsDefaultExpandAll { get; set; } = false;
|
||||
|
||||
#endregion
|
||||
@@ -239,12 +239,7 @@ public class TreeView : AvaloniaTreeView,
|
||||
|
||||
public void CheckedSubTree(TreeViewItem item)
|
||||
{
|
||||
if (!IsCheckable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item.IsEnabled || !item.IsCheckable)
|
||||
if (!item.IsEnabled || item.ToggleType == ItemToggleType.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -272,12 +267,7 @@ public class TreeView : AvaloniaTreeView,
|
||||
|
||||
public void UnCheckedSubTree(TreeViewItem item)
|
||||
{
|
||||
if (!IsCheckable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!item.IsEnabled || !item.IsCheckable)
|
||||
if (!item.IsEnabled || item.ToggleType == ItemToggleType.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -339,8 +329,8 @@ public class TreeView : AvaloniaTreeView,
|
||||
BindUtils.RelayBind(this, IsShowIconProperty, treeViewItem, TreeViewItem.IsShowIconProperty);
|
||||
BindUtils.RelayBind(this, IsShowLeafIconProperty, treeViewItem,
|
||||
TreeViewItem.IsShowLeafIconProperty);
|
||||
BindUtils.RelayBind(this, IsCheckableProperty, treeViewItem, TreeViewItem.IsCheckboxVisibleProperty);
|
||||
BindUtils.RelayBind(this, IsSwitcherRotationProperty, treeViewItem, TreeViewItem.IsSwitcherRotationProperty);
|
||||
BindUtils.RelayBind(this, ToggleTypeProperty, treeViewItem, TreeViewItem.ToggleTypeProperty);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,13 +28,9 @@ using AvaloniaTreeItem = Avalonia.Controls.TreeViewItem;
|
||||
|
||||
[PseudoClasses(TreeViewPseudoClass.NodeToggleTypeCheckBox, TreeViewPseudoClass.NodeToggleTypeRadio, TreeViewPseudoClass.TreeNodeHover)]
|
||||
public class TreeViewItem : AvaloniaTreeItem,
|
||||
IResourceBindingManager,
|
||||
IRadioButton
|
||||
IResourceBindingManager
|
||||
{
|
||||
#region 公共属性定义
|
||||
public static readonly StyledProperty<bool> IsCheckableProperty =
|
||||
AvaloniaProperty.Register<TreeViewItem, bool>(nameof(IsCheckable), true);
|
||||
|
||||
public static readonly StyledProperty<Icon?> IconProperty
|
||||
= AvaloniaProperty.Register<TreeViewItem, Icon?>(nameof(Icon));
|
||||
|
||||
@@ -67,18 +63,9 @@ public class TreeViewItem : AvaloniaTreeItem,
|
||||
public static readonly StyledProperty<bool> IsLoadingProperty =
|
||||
AvaloniaProperty.Register<TreeViewItem, bool>(nameof(IsLoading), false);
|
||||
|
||||
public static readonly StyledProperty<ItemToggleType> ToggleTypeProperty =
|
||||
AvaloniaProperty.Register<TreeViewItem, ItemToggleType>(nameof(ToggleType));
|
||||
|
||||
public static readonly StyledProperty<string?> GroupNameProperty =
|
||||
RadioButton.GroupNameProperty.AddOwner<TreeViewItem>();
|
||||
|
||||
public bool IsCheckable
|
||||
{
|
||||
get => GetValue(IsCheckableProperty);
|
||||
set => SetValue(IsCheckableProperty, value);
|
||||
}
|
||||
|
||||
public Icon? Icon
|
||||
{
|
||||
get => GetValue(IconProperty);
|
||||
@@ -140,12 +127,6 @@ public class TreeViewItem : AvaloniaTreeItem,
|
||||
get => GetValue(IsLoadingProperty);
|
||||
set => SetValue(IsLoadingProperty, value);
|
||||
}
|
||||
|
||||
public ItemToggleType ToggleType
|
||||
{
|
||||
get => GetValue(ToggleTypeProperty);
|
||||
set => SetValue(ToggleTypeProperty, value);
|
||||
}
|
||||
|
||||
public string? GroupName
|
||||
{
|
||||
@@ -198,16 +179,6 @@ public class TreeViewItem : AvaloniaTreeItem,
|
||||
o => o.IconEffectiveVisible,
|
||||
(o, v) => o.IconEffectiveVisible = v);
|
||||
|
||||
internal static readonly DirectProperty<TreeViewItem, bool> IsCheckboxVisibleProperty =
|
||||
AvaloniaProperty.RegisterDirect<TreeViewItem, bool>(nameof(IsCheckboxVisible),
|
||||
o => o.IsCheckboxVisible,
|
||||
(o, v) => o.IsCheckboxVisible = v);
|
||||
|
||||
internal static readonly DirectProperty<TreeViewItem, bool> IsCheckboxEnableProperty =
|
||||
AvaloniaProperty.RegisterDirect<TreeViewItem, bool>(nameof(IsCheckboxEnable),
|
||||
o => o.IsCheckboxEnable,
|
||||
(o, v) => o.IsCheckboxEnable = v);
|
||||
|
||||
internal static readonly DirectProperty<TreeViewItem, bool> IsDraggingProperty =
|
||||
AvaloniaProperty.RegisterDirect<TreeViewItem, bool>(nameof(IsDragging),
|
||||
o => o.IsDragging,
|
||||
@@ -243,6 +214,9 @@ public class TreeViewItem : AvaloniaTreeItem,
|
||||
nameof(IsSwitcherRotation),
|
||||
o => o.IsSwitcherRotation,
|
||||
(o, v) => o.IsSwitcherRotation = v);
|
||||
|
||||
internal static readonly StyledProperty<ItemToggleType> ToggleTypeProperty =
|
||||
TreeView.ToggleTypeProperty.AddOwner<TreeViewItem>();
|
||||
|
||||
private double _titleHeight;
|
||||
|
||||
@@ -284,22 +258,6 @@ public class TreeViewItem : AvaloniaTreeItem,
|
||||
set => SetAndRaise(IconEffectiveVisibleProperty, ref _iconEffectiveVisible, value);
|
||||
}
|
||||
|
||||
private bool _isCheckboxVisible;
|
||||
|
||||
internal bool IsCheckboxVisible
|
||||
{
|
||||
get => _isCheckboxVisible;
|
||||
set => SetAndRaise(IsCheckboxVisibleProperty, ref _isCheckboxVisible, value);
|
||||
}
|
||||
|
||||
private bool _isCheckboxEnable;
|
||||
|
||||
internal bool IsCheckboxEnable
|
||||
{
|
||||
get => _isCheckboxEnable;
|
||||
set => SetAndRaise(IsCheckboxEnableProperty, ref _isCheckboxEnable, value);
|
||||
}
|
||||
|
||||
private bool _isDragging;
|
||||
|
||||
internal bool IsDragging
|
||||
@@ -357,6 +315,12 @@ public class TreeViewItem : AvaloniaTreeItem,
|
||||
get => _isSwitcherRotation;
|
||||
set => SetAndRaise(IsSwitcherRotationProperty, ref _isSwitcherRotation, value);
|
||||
}
|
||||
|
||||
internal ItemToggleType ToggleType
|
||||
{
|
||||
get => GetValue(ToggleTypeProperty);
|
||||
set => SetValue(ToggleTypeProperty, value);
|
||||
}
|
||||
|
||||
internal TreeView? OwnerTreeView { get; set; }
|
||||
|
||||
@@ -406,7 +370,6 @@ public class TreeViewItem : AvaloniaTreeItem,
|
||||
}
|
||||
|
||||
SetupSwitcherButtonIconMode();
|
||||
SetupCheckBoxEnabled();
|
||||
}
|
||||
|
||||
protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
|
||||
@@ -457,11 +420,6 @@ public class TreeViewItem : AvaloniaTreeItem,
|
||||
{
|
||||
CalculateEffectiveBgRect();
|
||||
}
|
||||
else if (change.Property == IsEnabledProperty ||
|
||||
change.Property == IsCheckableProperty)
|
||||
{
|
||||
SetupCheckBoxEnabled();
|
||||
}
|
||||
else if (change.Property == IsCheckedProperty)
|
||||
{
|
||||
// 我们处理某个节点的点击只有 true 或者 false
|
||||
@@ -585,7 +543,7 @@ public class TreeViewItem : AvaloniaTreeItem,
|
||||
_switcherButton.IsNodeAnimating = true;
|
||||
}
|
||||
|
||||
var motion = OwnerTreeView.OpenMotion ?? new CollapseMotion(Direction.Top, null, new CubicEaseIn());
|
||||
var motion = OwnerTreeView.CloseMotion ?? new CollapseMotion(Direction.Top, null, new CubicEaseIn());
|
||||
motion.Duration = OwnerTreeView.MotionDuration;
|
||||
|
||||
MotionInvoker.Invoke(_itemsPresenterMotionActor, motion, null, () =>
|
||||
@@ -775,19 +733,7 @@ public class TreeViewItem : AvaloniaTreeItem,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetupCheckBoxEnabled()
|
||||
{
|
||||
if (!IsEnabled)
|
||||
{
|
||||
IsCheckboxEnable = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
IsCheckboxEnable = IsCheckable;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void HandleFrameEntered(object? sender, PointerEventArgs? args)
|
||||
{
|
||||
if (NodeHoverMode != TreeItemHoverMode.WholeLine)
|
||||
|
||||
Reference in New Issue
Block a user