feat: selected item is now two-way binding by default.
This commit is contained in:
@@ -31,17 +31,22 @@
|
|||||||
<u:TreeComboBox
|
<u:TreeComboBox
|
||||||
Width="300"
|
Width="300"
|
||||||
HorizontalAlignment="Left"
|
HorizontalAlignment="Left"
|
||||||
|
SelectedItem="{Binding SelectedItem}"
|
||||||
ItemsSource="{Binding Items}">
|
ItemsSource="{Binding Items}">
|
||||||
<u:TreeComboBox.ItemTemplate>
|
<u:TreeComboBox.ItemTemplate>
|
||||||
<TreeDataTemplate ItemsSource="{Binding Children}">
|
<TreeDataTemplate ItemsSource="{Binding Children}">
|
||||||
<TextBlock Text="{Binding ItemName}" />
|
<TextBlock Text="{Binding ItemName}" />
|
||||||
</TreeDataTemplate>
|
</TreeDataTemplate>
|
||||||
</u:TreeComboBox.ItemTemplate>
|
</u:TreeComboBox.ItemTemplate>
|
||||||
<u:TreeComboBox.SelectedItemTemplate>
|
|
||||||
<DataTemplate>
|
|
||||||
<TextBlock Text="{Binding ItemName}" />
|
|
||||||
</DataTemplate>
|
|
||||||
</u:TreeComboBox.SelectedItemTemplate>
|
|
||||||
</u:TreeComboBox>
|
</u:TreeComboBox>
|
||||||
|
|
||||||
|
<ContentControl Content="{Binding SelectedItem}">
|
||||||
|
<ContentControl.ContentTemplate>
|
||||||
|
<DataTemplate DataType="vm:TreeComboBoxItemViewModel">
|
||||||
|
<TextBlock Text="{Binding ItemName}"></TextBlock>
|
||||||
|
</DataTemplate>
|
||||||
|
</ContentControl.ContentTemplate>
|
||||||
|
</ContentControl>
|
||||||
|
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@@ -3,8 +3,9 @@ using CommunityToolkit.Mvvm.ComponentModel;
|
|||||||
|
|
||||||
namespace Ursa.Demo.ViewModels;
|
namespace Ursa.Demo.ViewModels;
|
||||||
|
|
||||||
public class TreeComboBoxDemoViewModel: ObservableObject
|
public partial class TreeComboBoxDemoViewModel: ObservableObject
|
||||||
{
|
{
|
||||||
|
[ObservableProperty] private TreeComboBoxItemViewModel? _selectedItem;
|
||||||
public List<TreeComboBoxItemViewModel> Items { get; set; }
|
public List<TreeComboBoxItemViewModel> Items { get; set; }
|
||||||
|
|
||||||
public TreeComboBoxDemoViewModel()
|
public TreeComboBoxDemoViewModel()
|
||||||
|
|||||||
@@ -2,10 +2,12 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:u="https://irihi.tech/ursa"
|
xmlns:u="https://irihi.tech/ursa"
|
||||||
xmlns:iri="https://irihi.tech/shared"
|
xmlns:iri="https://irihi.tech/shared"
|
||||||
xmlns:converters="clr-namespace:Avalonia.Controls.Converters;assembly=Avalonia.Controls">
|
xmlns:converters="clr-namespace:Avalonia.Controls.Converters;assembly=Avalonia.Controls"
|
||||||
|
xmlns:converters1="clr-namespace:Ursa.Themes.Semi.Converters">
|
||||||
<!-- Add Resources Here -->
|
<!-- Add Resources Here -->
|
||||||
|
|
||||||
<converters:MarginMultiplierConverter x:Key="LeftMarginConverter" Indent="20" Left="True"/>
|
<converters:MarginMultiplierConverter x:Key="LeftMarginConverter" Indent="20" Left="True"/>
|
||||||
|
<converters1:SelectedItemTemplateConverter x:Key="SelectedItemTemplateConverter"/>
|
||||||
|
|
||||||
<ControlTheme x:Key="{x:Type u:TreeComboBox}" TargetType="u:TreeComboBox">
|
<ControlTheme x:Key="{x:Type u:TreeComboBox}" TargetType="u:TreeComboBox">
|
||||||
<Setter Property="Padding" Value="{DynamicResource ComboBoxSelectorDefaultPadding}"/>
|
<Setter Property="Padding" Value="{DynamicResource ComboBoxSelectorDefaultPadding}"/>
|
||||||
@@ -17,7 +19,7 @@
|
|||||||
<Setter Property="Cursor" Value="Hand"/>
|
<Setter Property="Cursor" Value="Hand"/>
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate TargetType="u:TreeComboBox">
|
<ControlTemplate TargetType="u:TreeComboBox">
|
||||||
<Grid ColumnDefinitions="*, Auto, 32">
|
<Grid ColumnDefinitions="*, Auto, Auto">
|
||||||
<Border Grid.Column="0"
|
<Border Grid.Column="0"
|
||||||
Name="Background"
|
Name="Background"
|
||||||
Grid.ColumnSpan="3"
|
Grid.ColumnSpan="3"
|
||||||
@@ -44,8 +46,14 @@
|
|||||||
Margin="{TemplateBinding Padding}"
|
Margin="{TemplateBinding Padding}"
|
||||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||||
VerticalAlignment="Center"
|
VerticalAlignment="Center"
|
||||||
ContentTemplate="{TemplateBinding SelectedItemTemplate}"
|
Content="{TemplateBinding SelectionBoxItem}">
|
||||||
Content="{TemplateBinding SelectionBoxItem}"/>
|
<ContentPresenter.ContentTemplate>
|
||||||
|
<MultiBinding Converter="{x:Static converters1:SelectedItemTemplateConverter.Instance}">
|
||||||
|
<TemplateBinding Property="SelectedItemTemplate"/>
|
||||||
|
<TemplateBinding Property="ItemTemplate"/>
|
||||||
|
</MultiBinding>
|
||||||
|
</ContentPresenter.ContentTemplate>
|
||||||
|
</ContentPresenter>
|
||||||
<Border
|
<Border
|
||||||
x:Name="DropDownOverlay"
|
x:Name="DropDownOverlay"
|
||||||
Grid.Column="2"
|
Grid.Column="2"
|
||||||
@@ -54,19 +62,18 @@
|
|||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
Background="Transparent"
|
Background="Transparent"
|
||||||
IsVisible="False" />
|
IsVisible="False" />
|
||||||
|
<Panel Grid.Column="2" Width="32" IsHitTestVisible="False">
|
||||||
<PathIcon
|
<PathIcon
|
||||||
x:Name="DropDownGlyph"
|
x:Name="DropDownGlyph"
|
||||||
Grid.Column="2"
|
Width="12"
|
||||||
Width="12"
|
Height="12"
|
||||||
Height="12"
|
Margin="0,0,10,0"
|
||||||
Margin="0,0,10,0"
|
HorizontalAlignment="Right"
|
||||||
HorizontalAlignment="Right"
|
VerticalAlignment="Center"
|
||||||
VerticalAlignment="Center"
|
Data="{DynamicResource ComboBoxIcon}"
|
||||||
Data="{DynamicResource ComboBoxIcon}"
|
Foreground="{DynamicResource ComboBoxIconDefaultForeground}"
|
||||||
Foreground="{DynamicResource ComboBoxIconDefaultForeground}"
|
UseLayoutRounding="False" />
|
||||||
IsHitTestVisible="False"
|
</Panel>
|
||||||
UseLayoutRounding="False" />
|
|
||||||
<Popup
|
<Popup
|
||||||
Name="{x:Static iri:PartNames.PART_Popup}"
|
Name="{x:Static iri:PartNames.PART_Popup}"
|
||||||
Grid.Column="0"
|
Grid.Column="0"
|
||||||
@@ -77,7 +84,7 @@
|
|||||||
PlacementTarget="Background"
|
PlacementTarget="Background"
|
||||||
WindowManagerAddShadowHint="False"
|
WindowManagerAddShadowHint="False"
|
||||||
IsLightDismissEnabled="True"
|
IsLightDismissEnabled="True"
|
||||||
IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}">
|
IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}">
|
||||||
<Border
|
<Border
|
||||||
Name="PopupBorder"
|
Name="PopupBorder"
|
||||||
Margin="0 4"
|
Margin="0 4"
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using System.Globalization;
|
||||||
|
using Avalonia;
|
||||||
|
using Avalonia.Controls.Templates;
|
||||||
|
using Avalonia.Data.Converters;
|
||||||
|
|
||||||
|
namespace Ursa.Themes.Semi.Converters;
|
||||||
|
|
||||||
|
public class SelectedItemTemplateConverter: IMultiValueConverter
|
||||||
|
{
|
||||||
|
public static SelectedItemTemplateConverter Instance { get; } = new SelectedItemTemplateConverter();
|
||||||
|
|
||||||
|
public object? Convert(IList<object?> values, Type targetType, object? parameter, CultureInfo culture)
|
||||||
|
{
|
||||||
|
if(values.Count>0 && values[0] is IDataTemplate template1)
|
||||||
|
{
|
||||||
|
return template1;
|
||||||
|
}
|
||||||
|
if(values.Count>1 && values[1] is IDataTemplate template2)
|
||||||
|
{
|
||||||
|
return template2;
|
||||||
|
}
|
||||||
|
return AvaloniaProperty.UnsetValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,19 +4,21 @@ using Avalonia.Controls.Metadata;
|
|||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Controls.Shapes;
|
using Avalonia.Controls.Shapes;
|
||||||
using Avalonia.Controls.Templates;
|
using Avalonia.Controls.Templates;
|
||||||
|
using Avalonia.Data;
|
||||||
using Avalonia.Input;
|
using Avalonia.Input;
|
||||||
using Avalonia.Layout;
|
using Avalonia.Layout;
|
||||||
using Avalonia.Media;
|
using Avalonia.Media;
|
||||||
using Avalonia.Metadata;
|
using Avalonia.Metadata;
|
||||||
using Avalonia.VisualTree;
|
using Avalonia.VisualTree;
|
||||||
using Irihi.Avalonia.Shared.Common;
|
using Irihi.Avalonia.Shared.Common;
|
||||||
|
using Irihi.Avalonia.Shared.Contracts;
|
||||||
using Size = Avalonia.Size;
|
using Size = Avalonia.Size;
|
||||||
|
|
||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
[TemplatePart(PartNames.PART_Popup, typeof(Popup))]
|
[TemplatePart(PartNames.PART_Popup, typeof(Popup))]
|
||||||
public class TreeComboBox: ItemsControl
|
public class TreeComboBox: ItemsControl, IClearControl
|
||||||
{
|
{
|
||||||
private Popup? _popup;
|
private Popup? _popup;
|
||||||
|
|
||||||
@@ -89,8 +91,10 @@ public class TreeComboBox: ItemsControl
|
|||||||
|
|
||||||
private object? _selectedItem;
|
private object? _selectedItem;
|
||||||
|
|
||||||
public static readonly DirectProperty<TreeComboBox, object?> SelectedItemProperty = AvaloniaProperty.RegisterDirect<TreeComboBox, object?>(
|
public static readonly DirectProperty<TreeComboBox, object?> SelectedItemProperty =
|
||||||
nameof(SelectedItem), o => o.SelectedItem, (o, v) => o.SelectedItem = v);
|
AvaloniaProperty.RegisterDirect<TreeComboBox, object?>(
|
||||||
|
nameof(SelectedItem), o => o.SelectedItem, (o, v) => o.SelectedItem = v,
|
||||||
|
defaultBindingMode: BindingMode.TwoWay);
|
||||||
|
|
||||||
public object? SelectedItem
|
public object? SelectedItem
|
||||||
{
|
{
|
||||||
@@ -284,4 +288,9 @@ public class TreeComboBox: ItemsControl
|
|||||||
treeComboBoxItem.IsSelected = selected;
|
treeComboBoxItem.IsSelected = selected;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
SelectedItem = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user