commit
b6fe246293
|
@ -1,13 +1,14 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.2</TargetFramework>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>netcoreapp3.0</TargetFramework>
|
||||
<TargetLatestRuntimePatch>true</TargetLatestRuntimePatch>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia.LinuxFramebuffer" Version="0.9.0" />
|
||||
<ProjectReference Include="..\ControlCatalog\ControlCatalog.csproj" />
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.8.1-cibuild0002425-beta"/>
|
||||
<PackageReference Include="Avalonia.Desktop" Version="0.9.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -1,25 +1,52 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using Avalonia;
|
||||
using Avalonia.Skia;
|
||||
using Avalonia.ReactiveUI;
|
||||
using Avalonia.Dialogs;
|
||||
|
||||
namespace ControlCatalog.NetCore
|
||||
{
|
||||
static class Program
|
||||
{
|
||||
|
||||
static void Main(string[] args)
|
||||
[STAThread]
|
||||
static int Main(string[] args)
|
||||
{
|
||||
Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA);
|
||||
BuildAvaloniaApp().Start(AppMain, args);
|
||||
}
|
||||
if (args.Contains("--wait-for-attach"))
|
||||
{
|
||||
Console.WriteLine("Attach debugger and use 'Set next statement'");
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
if (Debugger.IsAttached)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void AppMain(Application app, string[] args)
|
||||
{
|
||||
app.Run(new MainWindow());
|
||||
var builder = BuildAvaloniaApp();
|
||||
|
||||
double GetScaling()
|
||||
{
|
||||
var idx = Array.IndexOf(args, "--scaling");
|
||||
if (idx != 0 && args.Length > idx + 1 &&
|
||||
double.TryParse(args[idx + 1], NumberStyles.Any, CultureInfo.InvariantCulture, out var scaling))
|
||||
return scaling;
|
||||
return 1;
|
||||
}
|
||||
if (args.Contains("--fbdev"))
|
||||
{
|
||||
SilenceConsole();
|
||||
return builder.StartLinuxFbDev(args, scaling: GetScaling());
|
||||
}
|
||||
else if (args.Contains("--drm"))
|
||||
{
|
||||
SilenceConsole();
|
||||
return builder.StartLinuxDrm(args, scaling: GetScaling());
|
||||
}
|
||||
else
|
||||
return builder.StartWithClassicDesktopLifetime(args);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -28,7 +55,29 @@ namespace ControlCatalog.NetCore
|
|||
public static AppBuilder BuildAvaloniaApp()
|
||||
=> AppBuilder.Configure<App>()
|
||||
.UsePlatformDetect()
|
||||
.With(new X11PlatformOptions
|
||||
{
|
||||
EnableMultiTouch = true,
|
||||
UseDBusMenu = true
|
||||
})
|
||||
.With(new Win32PlatformOptions
|
||||
{
|
||||
EnableMultitouch = true,
|
||||
AllowEglInitialization = true
|
||||
})
|
||||
.UseSkia()
|
||||
.UseReactiveUI();
|
||||
.UseReactiveUI()
|
||||
.UseManagedSystemDialogs();
|
||||
|
||||
static void SilenceConsole()
|
||||
{
|
||||
new Thread(() =>
|
||||
{
|
||||
Console.CursorVisible = false;
|
||||
while (true)
|
||||
Console.ReadKey(true);
|
||||
})
|
||||
{ IsBackground = true }.Start();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,9 +2,9 @@
|
|||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="ControlCatalog.App">
|
||||
<Application.Styles>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
|
||||
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Default.xaml"/>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Default/DefaultTheme.xaml"/>
|
||||
<StyleInclude Source="avares://Avalonia.Themes.Default/Accents/BaseLight.xaml"/>
|
||||
<StyleInclude Source="avares://Avalonia.Controls.DataGrid/Themes/Default.xaml"/>
|
||||
<Style Selector="TextBlock.h1">
|
||||
<Setter Property="FontSize" Value="{DynamicResource FontSizeLarge}"/>
|
||||
<Setter Property="FontWeight" Value="Medium"/>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
namespace ControlCatalog
|
||||
|
@ -9,5 +10,15 @@ namespace ControlCatalog
|
|||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
public override void OnFrameworkInitializationCompleted()
|
||||
{
|
||||
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktopLifetime)
|
||||
desktopLifetime.MainWindow = new MainWindow();
|
||||
else if (ApplicationLifetime is ISingleViewApplicationLifetime singleViewLifetime)
|
||||
singleViewLifetime.MainView = new MainView();
|
||||
|
||||
base.OnFrameworkInitializationCompleted();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Avalonia" Version="0.8.1-cibuild0002425-beta" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.8.1-cibuild0002425-beta" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="0.8.1-cibuild0002425-beta" />
|
||||
<PackageReference Include="Avalonia" Version="0.9.0" />
|
||||
<PackageReference Include="Avalonia.ReactiveUI" Version="0.9.0" />
|
||||
<PackageReference Include="Avalonia.Controls.DataGrid" Version="0.9.0" />
|
||||
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
@ -3,6 +3,31 @@
|
|||
x:Class="ControlCatalog.DecoratedWindow"
|
||||
Title="Avalonia Control Gallery"
|
||||
xmlns:local="clr-namespace:ControlCatalog" HasSystemDecorations="False" Name="Window">
|
||||
<NativeMenu.Menu>
|
||||
<NativeMenu>
|
||||
<NativeMenuItem Header="Decorated">
|
||||
<NativeMenuItem.Menu>
|
||||
<NativeMenu>
|
||||
<NativeMenuItem Header="Open"/>
|
||||
<NativeMenuItem Header="Recent">
|
||||
<NativeMenuItem.Menu>
|
||||
<NativeMenu/>
|
||||
</NativeMenuItem.Menu>
|
||||
</NativeMenuItem>
|
||||
<NativeMenuItem Header="Quit Avalonia" Gesture="CMD+Q"/>
|
||||
</NativeMenu>
|
||||
</NativeMenuItem.Menu>
|
||||
</NativeMenuItem>
|
||||
<NativeMenuItem Header="Edit">
|
||||
<NativeMenuItem.Menu>
|
||||
<NativeMenu>
|
||||
<NativeMenuItem Header="Copy"/>
|
||||
<NativeMenuItem Header="Paste"/>
|
||||
</NativeMenu>
|
||||
</NativeMenuItem.Menu>
|
||||
</NativeMenuItem>
|
||||
</NativeMenu>
|
||||
</NativeMenu.Menu>
|
||||
<Grid RowDefinitions="5,*,5" ColumnDefinitions="5,*,5">
|
||||
<DockPanel Grid.Column="1" Grid.Row="1" >
|
||||
<Grid Name="TitleBar" Background="LightBlue" DockPanel.Dock="Top" ColumnDefinitions="Auto,*,Auto">
|
||||
|
|
|
@ -18,23 +18,23 @@ namespace ControlCatalog
|
|||
{
|
||||
var ctl = this.FindControl<Control>(name);
|
||||
ctl.Cursor = new Cursor(cursor);
|
||||
ctl.PointerPressed += delegate
|
||||
ctl.PointerPressed += (i, e) =>
|
||||
{
|
||||
PlatformImpl?.BeginResizeDrag(edge);
|
||||
PlatformImpl?.BeginResizeDrag(edge, e);
|
||||
};
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
this.FindControl<Control>("TitleBar").PointerPressed += delegate
|
||||
this.FindControl<Control>("TitleBar").PointerPressed += (i, e) =>
|
||||
{
|
||||
PlatformImpl?.BeginMoveDrag();
|
||||
PlatformImpl?.BeginMoveDrag(e);
|
||||
};
|
||||
SetupSide("Left", StandardCursorType.LeftSide, WindowEdge.West);
|
||||
SetupSide("Right", StandardCursorType.RightSide, WindowEdge.East);
|
||||
SetupSide("Top", StandardCursorType.TopSide, WindowEdge.North);
|
||||
SetupSide("Bottom", StandardCursorType.BottomSize, WindowEdge.South);
|
||||
SetupSide("Bottom", StandardCursorType.BottomSide, WindowEdge.South);
|
||||
SetupSide("TopLeft", StandardCursorType.TopLeftCorner, WindowEdge.NorthWest);
|
||||
SetupSide("TopRight", StandardCursorType.TopRightCorner, WindowEdge.NorthEast);
|
||||
SetupSide("BottomLeft", StandardCursorType.BottomLeftCorner, WindowEdge.SouthWest);
|
||||
|
|
|
@ -6,10 +6,13 @@
|
|||
Foreground="{DynamicResource ThemeForegroundBrush}"
|
||||
FontSize="{DynamicResource FontSizeNormal}">
|
||||
<Grid>
|
||||
<ComboBox x:Name="Themes" SelectedIndex="0" Width="100" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Bottom">
|
||||
<ComboBoxItem>Light</ComboBoxItem>
|
||||
<ComboBoxItem>Dark</ComboBoxItem>
|
||||
</ComboBox>
|
||||
<Grid.Styles>
|
||||
<Style Selector="TextBlock.h2">
|
||||
<Setter Property="TextWrapping" Value="Wrap"/>
|
||||
<Setter Property="MaxWidth" Value="400"/>
|
||||
<Setter Property="HorizontalAlignment" Value="Left"/>
|
||||
</Style>
|
||||
</Grid.Styles>
|
||||
<TabControl Classes="sidebar" Name="Sidebar">
|
||||
<TabItem Header="AutoCompleteBox"><pages:AutoCompleteBoxPage/></TabItem>
|
||||
<TabItem Header="Border"><pages:BorderPage/></TabItem>
|
||||
|
@ -21,24 +24,41 @@
|
|||
<TabItem Header="CheckBox"><pages:CheckBoxPage/></TabItem>
|
||||
<TabItem Header="ComboBox"><pages:ComboBoxPage/></TabItem>
|
||||
<TabItem Header="ContextMenu"><pages:ContextMenuPage/></TabItem>
|
||||
<TabItem Header="DataGrid"><pages:DataGridPage/></TabItem>
|
||||
<TabItem Header="DataGrid"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
|
||||
<pages:DataGridPage/>
|
||||
</TabItem>
|
||||
<TabItem Header="DatePicker"><pages:DatePickerPage/></TabItem>
|
||||
<TabItem Header="Drag+Drop"><pages:DragAndDropPage/></TabItem>
|
||||
<TabItem Header="Expander"><pages:ExpanderPage/></TabItem>
|
||||
<TabItem Header="Image"><pages:ImagePage/></TabItem>
|
||||
<TabItem Header="ItemsRepeater"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
|
||||
<pages:ItemsRepeaterPage/>
|
||||
</TabItem>
|
||||
<TabItem Header="LayoutTransformControl"><pages:LayoutTransformControlPage/></TabItem>
|
||||
<TabItem Header="ListBox"><pages:ListBoxPage/></TabItem>
|
||||
<TabItem Header="Menu"><pages:MenuPage/></TabItem>
|
||||
<TabItem Header="Notifications"><pages:NotificationsPage/></TabItem>
|
||||
<TabItem Header="NumericUpDown"><pages:NumericUpDownPage/></TabItem>
|
||||
<TabItem Header="NumericUpDown"><pages:NumericUpDownPage/></TabItem>
|
||||
<TabItem Header="Pointers (Touch)"><pages:PointersPage/></TabItem>
|
||||
<TabItem Header="ProgressBar"><pages:ProgressBarPage/></TabItem>
|
||||
<TabItem Header="RadioButton"><pages:RadioButtonPage/></TabItem>
|
||||
<TabItem Header="Slider"><pages:SliderPage/></TabItem>
|
||||
<TabItem Header="TabControl"><pages:TabControlPage/></TabItem>
|
||||
<TabItem Header="TabStrip"><pages:TabStripPage/></TabItem>
|
||||
<TabItem Header="TextBox"><pages:TextBoxPage/></TabItem>
|
||||
<TabItem Header="ToolTip"><pages:ToolTipPage/></TabItem>
|
||||
<TabItem Header="TreeView"><pages:TreeViewPage/></TabItem>
|
||||
<TabItem Header="Viewbox"><pages:ViewboxPage/></TabItem>
|
||||
<TabControl.Tag>
|
||||
<ComboBox x:Name="Themes" SelectedIndex="0" Width="100" Margin="8" HorizontalAlignment="Right" VerticalAlignment="Bottom">
|
||||
<ComboBoxItem>Light</ComboBoxItem>
|
||||
<ComboBoxItem>Dark</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</TabControl.Tag>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
<Window xmlns="https://github.com/avaloniaui" MinWidth="500" MinHeight="300"
|
||||
Width="1024" Height="800"
|
||||
xmlns:pages="clr-namespace:ControlCatalog.Pages"
|
||||
Title="Avalonia Control Gallery"
|
||||
Icon="/Assets/test_icon.ico"
|
||||
|
@ -7,12 +8,49 @@
|
|||
xmlns:vm="clr-namespace:ControlCatalog.ViewModels"
|
||||
xmlns:v="clr-namespace:ControlCatalog.Views"
|
||||
x:Class="ControlCatalog.MainWindow">
|
||||
<Window.DataTemplates>
|
||||
<DataTemplate DataType="vm:NotificationViewModel">
|
||||
<v:CustomNotificationView />
|
||||
</DataTemplate>
|
||||
</Window.DataTemplates>
|
||||
<Panel>
|
||||
<local:MainView/>
|
||||
</Panel>
|
||||
|
||||
<NativeMenu.Menu>
|
||||
<NativeMenu>
|
||||
<NativeMenuItem Header="File">
|
||||
<NativeMenuItem.Menu>
|
||||
<NativeMenu>
|
||||
<NativeMenuItem Header="Open" Clicked="OnOpenClicked"/>
|
||||
<NativeMenuItemSeperator/>
|
||||
<NativeMenuItem Header="Recent">
|
||||
<NativeMenuItem.Menu>
|
||||
<NativeMenu/>
|
||||
</NativeMenuItem.Menu>
|
||||
</NativeMenuItem>
|
||||
<NativeMenuItemSeperator/>
|
||||
<NativeMenuItem Header="Quit Avalonia" Clicked="OnCloseClicked" Gesture="CMD+Q"/>
|
||||
</NativeMenu>
|
||||
</NativeMenuItem.Menu>
|
||||
</NativeMenuItem>
|
||||
<NativeMenuItem Header="Edit">
|
||||
<NativeMenuItem.Menu>
|
||||
<NativeMenu>
|
||||
<NativeMenuItem Header="Copy"/>
|
||||
<NativeMenuItem Header="Paste"/>
|
||||
</NativeMenu>
|
||||
</NativeMenuItem.Menu>
|
||||
</NativeMenuItem>
|
||||
</NativeMenu>
|
||||
</NativeMenu.Menu>
|
||||
|
||||
<Window.DataTemplates>
|
||||
<DataTemplate DataType="vm:NotificationViewModel">
|
||||
<v:CustomNotificationView />
|
||||
</DataTemplate>
|
||||
</Window.DataTemplates>
|
||||
<DockPanel LastChildFill="True">
|
||||
<Menu Name="MainMenu" DockPanel.Dock="Top">
|
||||
<MenuItem Header="File">
|
||||
<MenuItem Header="Exit" Command="{Binding ExitCommand}" />
|
||||
</MenuItem>
|
||||
<MenuItem Header="Help">
|
||||
<MenuItem Header="About" Command="{Binding AboutCommand}" />
|
||||
</MenuItem>
|
||||
</Menu>
|
||||
<local:MainView />
|
||||
</DockPanel>
|
||||
</Window>
|
||||
|
|
|
@ -6,6 +6,7 @@ using Avalonia.Markup.Xaml;
|
|||
using Avalonia.Threading;
|
||||
using ControlCatalog.ViewModels;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace ControlCatalog
|
||||
|
@ -13,6 +14,7 @@ namespace ControlCatalog
|
|||
public class MainWindow : Window
|
||||
{
|
||||
private WindowNotificationManager _notificationArea;
|
||||
private NativeMenu _recentMenu;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
|
@ -28,6 +30,27 @@ namespace ControlCatalog
|
|||
};
|
||||
|
||||
DataContext = new MainWindowViewModel(_notificationArea);
|
||||
_recentMenu = ((NativeMenu.GetMenu(this).Items[0] as NativeMenuItem).Menu.Items[2] as NativeMenuItem).Menu;
|
||||
var mainMenu = this.FindControl<Menu>("MainMenu");
|
||||
mainMenu.AttachedToVisualTree += MenuAttached;
|
||||
}
|
||||
|
||||
public void MenuAttached(object sender, VisualTreeAttachmentEventArgs e)
|
||||
{
|
||||
if (NativeMenu.GetIsNativeMenuExported(this) && sender is Menu mainMenu)
|
||||
{
|
||||
mainMenu.IsVisible = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnOpenClicked(object sender, EventArgs args)
|
||||
{
|
||||
_recentMenu.Items.Insert(0, new NativeMenuItem("Item " + (_recentMenu.Items.Count + 1)));
|
||||
}
|
||||
|
||||
public void OnCloseClicked(object sender, EventArgs args)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
|
|
|
@ -37,10 +37,6 @@
|
|||
|
||||
<StackPanel Orientation="Vertical">
|
||||
|
||||
<TextBlock Text="ValueMemeberSelector"/>
|
||||
<AutoCompleteBox Width="200"
|
||||
Margin="0,0,0,8"
|
||||
ValueMemberSelector="Capital"/>
|
||||
<TextBlock Text="ValueMemberBinding"/>
|
||||
<AutoCompleteBox Width="200"
|
||||
Margin="0,0,0,8"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using ControlCatalog.ViewModels;
|
||||
|
@ -12,6 +13,18 @@ namespace ControlCatalog.Pages
|
|||
DataContext = new ContextMenuPageViewModel();
|
||||
}
|
||||
|
||||
private ContextMenuPageViewModel _model;
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
if (_model != null)
|
||||
_model.View = null;
|
||||
_model = DataContext as ContextMenuPageViewModel;
|
||||
if (_model != null)
|
||||
_model.View = this;
|
||||
|
||||
base.OnDataContextChanged(e);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<Setter Property="Background" Value="{Binding Path=GDP, Mode=OneWay, Converter={StaticResource GDPConverter}}" />
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
<Grid RowDefinitions="Auto,Auto">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<StackPanel Orientation="Vertical" Spacing="4" Grid.Row="0">
|
||||
<TextBlock Classes="h1">DataGrid</TextBlock>
|
||||
<TextBlock Classes="h2">A control for displaying and interacting with a data source.</TextBlock>
|
||||
|
@ -52,4 +52,4 @@
|
|||
</TabItem>
|
||||
</TabControl>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
</UserControl>
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace ControlCatalog.Pages
|
|||
DataObject dragData = new DataObject();
|
||||
dragData.Set(DataFormats.Text, $"You have dragged text {++DragCount} times");
|
||||
|
||||
var result = await DragDrop.DoDragDrop(dragData, DragDropEffects.Copy);
|
||||
var result = await DragDrop.DoDragDrop(e, dragData, DragDropEffects.Copy);
|
||||
switch(result)
|
||||
{
|
||||
case DragDropEffects.Copy:
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
<UserControl xmlns="https://github.com/avaloniaui"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="ControlCatalog.Pages.ItemsRepeaterPage">
|
||||
<DockPanel>
|
||||
<StackPanel DockPanel.Dock="Top" Spacing="4" Margin="0 0 0 16">
|
||||
<TextBlock Classes="h1">ItemsRepeater</TextBlock>
|
||||
<TextBlock Classes="h2">A data-driven collection control that incorporates a flexible layout system, custom views, and virtualization.</TextBlock>
|
||||
</StackPanel>
|
||||
<StackPanel DockPanel.Dock="Right" Margin="8 0" Spacing="4">
|
||||
<ComboBox SelectedIndex="0" SelectionChanged="LayoutChanged">
|
||||
<ComboBoxItem>Stack - Vertical</ComboBoxItem>
|
||||
<ComboBoxItem>Stack - Horizontal</ComboBoxItem>
|
||||
<ComboBoxItem>UniformGrid - Vertical</ComboBoxItem>
|
||||
<ComboBoxItem>UniformGrid - Horizontal</ComboBoxItem>
|
||||
</ComboBox>
|
||||
<Button Command="{Binding AddItem}">Add Item</Button>
|
||||
<Button Command="{Binding RandomizeHeights}">Randomize Heights</Button>
|
||||
<Button Command="{Binding ResetItems}">Reset items</Button>
|
||||
</StackPanel>
|
||||
<Border BorderThickness="1" BorderBrush="{DynamicResource ThemeBorderMidBrush}" Margin="0 0 0 16">
|
||||
<ScrollViewer Name="scroller"
|
||||
HorizontalScrollBarVisibility="Auto"
|
||||
VerticalScrollBarVisibility="Auto">
|
||||
<ItemsRepeater Name="repeater" Background="Transparent" Items="{Binding Items}">
|
||||
<ItemsRepeater.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Focusable="True" Height="{Binding Height}" Text="{Binding Text}"/>
|
||||
</DataTemplate>
|
||||
</ItemsRepeater.ItemTemplate>
|
||||
</ItemsRepeater>
|
||||
</ScrollViewer>
|
||||
</Border>
|
||||
</DockPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,90 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using ControlCatalog.ViewModels;
|
||||
|
||||
namespace ControlCatalog.Pages
|
||||
{
|
||||
public class ItemsRepeaterPage : UserControl
|
||||
{
|
||||
private ItemsRepeater _repeater;
|
||||
private ScrollViewer _scroller;
|
||||
|
||||
public ItemsRepeaterPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
_repeater = this.FindControl<ItemsRepeater>("repeater");
|
||||
_scroller = this.FindControl<ScrollViewer>("scroller");
|
||||
_repeater.PointerPressed += RepeaterClick;
|
||||
_repeater.KeyDown += RepeaterOnKeyDown;
|
||||
DataContext = new ItemsRepeaterPageViewModel();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private void LayoutChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (_repeater == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var comboBox = (ComboBox)sender;
|
||||
|
||||
switch (comboBox.SelectedIndex)
|
||||
{
|
||||
case 0:
|
||||
_scroller.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
_scroller.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
_repeater.Layout = new StackLayout { Orientation = Orientation.Vertical };
|
||||
break;
|
||||
case 1:
|
||||
_scroller.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
_scroller.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
_repeater.Layout = new StackLayout { Orientation = Orientation.Horizontal };
|
||||
break;
|
||||
case 2:
|
||||
_scroller.HorizontalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
_scroller.VerticalScrollBarVisibility = ScrollBarVisibility.Disabled;
|
||||
_repeater.Layout = new UniformGridLayout
|
||||
{
|
||||
Orientation = Orientation.Vertical,
|
||||
MinItemWidth = 200,
|
||||
MinItemHeight = 200,
|
||||
};
|
||||
break;
|
||||
case 3:
|
||||
_scroller.HorizontalScrollBarVisibility = ScrollBarVisibility.Disabled;
|
||||
_scroller.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
_repeater.Layout = new UniformGridLayout
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
MinItemWidth = 200,
|
||||
MinItemHeight = 200,
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void RepeaterClick(object sender, PointerPressedEventArgs e)
|
||||
{
|
||||
var item = (e.Source as TextBlock)?.DataContext as ItemsRepeaterPageViewModel.Item;
|
||||
((ItemsRepeaterPageViewModel)DataContext).SelectedItem = item;
|
||||
}
|
||||
|
||||
private void RepeaterOnKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.F5)
|
||||
{
|
||||
((ItemsRepeaterPageViewModel)DataContext).ResetItems();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,7 +9,22 @@
|
|||
Margin="0,16,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
Spacing="16">
|
||||
<ListBox Items="{Binding}" Width="250" Height="350"></ListBox>
|
||||
<StackPanel Orientation="Vertical" Spacing="8">
|
||||
<ListBox Items="{Binding Items}" SelectedItem="{Binding SelectedItem}" AutoScrollToSelectedItem="True" SelectedItems="{Binding SelectedItems}" SelectionMode="{Binding SelectionMode}" Width="250" Height="350"></ListBox>
|
||||
|
||||
<Button Command="{Binding AddItemCommand}">Add</Button>
|
||||
|
||||
<Button Command="{Binding RemoveItemCommand}">Remove</Button>
|
||||
|
||||
<Button Command="{Binding SelectRandomItemCommand}">Select Random Item</Button>
|
||||
|
||||
<ComboBox SelectedIndex="{Binding SelectionMode, Mode=TwoWay}">
|
||||
<ComboBoxItem>Single</ComboBoxItem>
|
||||
<ComboBoxItem>Multiple</ComboBoxItem>
|
||||
<ComboBoxItem>Toggle</ComboBoxItem>
|
||||
<ComboBoxItem>AlwaysSelected</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace ControlCatalog.Pages
|
||||
{
|
||||
|
@ -11,9 +12,8 @@ namespace ControlCatalog.Pages
|
|||
{
|
||||
public ListBoxPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
DataContext = Enumerable.Range(1, 10).Select(i => $"Item {i}" )
|
||||
.ToArray();
|
||||
InitializeComponent();
|
||||
DataContext = new PageViewModel();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
|
@ -21,5 +21,64 @@ namespace ControlCatalog.Pages
|
|||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private class PageViewModel : ReactiveObject
|
||||
{
|
||||
private int _counter;
|
||||
private SelectionMode _selectionMode;
|
||||
|
||||
public PageViewModel()
|
||||
{
|
||||
Items = new ObservableCollection<string>(Enumerable.Range(1, 10000).Select(i => GenerateItem()));
|
||||
SelectedItems = new ObservableCollection<string>();
|
||||
|
||||
AddItemCommand = ReactiveCommand.Create(() => Items.Add(GenerateItem()));
|
||||
|
||||
RemoveItemCommand = ReactiveCommand.Create(() =>
|
||||
{
|
||||
while (SelectedItems.Count > 0)
|
||||
{
|
||||
Items.Remove(SelectedItems[0]);
|
||||
}
|
||||
});
|
||||
|
||||
SelectRandomItemCommand = ReactiveCommand.Create(() =>
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
SelectedItem = Items[random.Next(Items.Count - 1)];
|
||||
});
|
||||
}
|
||||
|
||||
public ObservableCollection<string> Items { get; }
|
||||
|
||||
private string _selectedItem;
|
||||
|
||||
public string SelectedItem
|
||||
{
|
||||
get { return _selectedItem; }
|
||||
set { this.RaiseAndSetIfChanged(ref _selectedItem, value); }
|
||||
}
|
||||
|
||||
|
||||
public ObservableCollection<string> SelectedItems { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> AddItemCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> RemoveItemCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> SelectRandomItemCommand { get; }
|
||||
|
||||
public SelectionMode SelectionMode
|
||||
{
|
||||
get => _selectionMode;
|
||||
set
|
||||
{
|
||||
SelectedItems.Clear();
|
||||
this.RaiseAndSetIfChanged(ref _selectionMode, value);
|
||||
}
|
||||
}
|
||||
|
||||
private string GenerateItem() => $"Item {_counter++.ToString()}";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,11 @@
|
|||
x:Class="ControlCatalog.Pages.MenuPage">
|
||||
<StackPanel Orientation="Vertical" Spacing="4">
|
||||
<TextBlock Classes="h1">Menu</TextBlock>
|
||||
<TextBlock Classes="h2">Exported menu fallback</TextBlock>
|
||||
<TextBlock>(Should be only visible on platforms without desktop-global menu bar)</TextBlock>
|
||||
<NativeMenuBar/>
|
||||
<TextBlock Classes="h2">A window menu</TextBlock>
|
||||
|
||||
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="0,16,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reactive;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -21,5 +22,18 @@ namespace ControlCatalog.Pages
|
|||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private MenuPageViewModel _model;
|
||||
protected override void OnDataContextChanged(EventArgs e)
|
||||
{
|
||||
if (_model != null)
|
||||
_model.View = null;
|
||||
_model = DataContext as MenuPageViewModel;
|
||||
if (_model != null)
|
||||
_model.View = this;
|
||||
|
||||
base.OnDataContextChanged(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Media;
|
||||
using Avalonia.Media.Immutable;
|
||||
|
||||
namespace ControlCatalog.Pages
|
||||
{
|
||||
public class PointersPage : Control
|
||||
{
|
||||
class PointerInfo
|
||||
{
|
||||
public Point Point { get; set; }
|
||||
public Color Color { get; set; }
|
||||
}
|
||||
|
||||
private static Color[] AllColors = new[]
|
||||
{
|
||||
Colors.Aqua,
|
||||
Colors.Beige,
|
||||
Colors.Chartreuse,
|
||||
Colors.Coral,
|
||||
Colors.Fuchsia,
|
||||
Colors.Crimson,
|
||||
Colors.Lavender,
|
||||
Colors.Orange,
|
||||
Colors.Orchid,
|
||||
Colors.ForestGreen,
|
||||
Colors.SteelBlue,
|
||||
Colors.PapayaWhip,
|
||||
Colors.PaleVioletRed,
|
||||
Colors.Goldenrod,
|
||||
Colors.Maroon,
|
||||
Colors.Moccasin,
|
||||
Colors.Navy,
|
||||
Colors.Wheat,
|
||||
Colors.Violet,
|
||||
Colors.Sienna,
|
||||
Colors.Indigo,
|
||||
Colors.Honeydew
|
||||
};
|
||||
|
||||
private Dictionary<IPointer, PointerInfo> _pointers = new Dictionary<IPointer, PointerInfo>();
|
||||
|
||||
public PointersPage()
|
||||
{
|
||||
ClipToBounds = true;
|
||||
}
|
||||
|
||||
void UpdatePointer(PointerEventArgs e)
|
||||
{
|
||||
if (!_pointers.TryGetValue(e.Pointer, out var info))
|
||||
{
|
||||
if (e.RoutedEvent == PointerMovedEvent)
|
||||
return;
|
||||
var colors = AllColors.Except(_pointers.Values.Select(c => c.Color)).ToArray();
|
||||
var color = colors[new Random().Next(0, colors.Length - 1)];
|
||||
_pointers[e.Pointer] = info = new PointerInfo {Color = color};
|
||||
}
|
||||
|
||||
info.Point = e.GetPosition(this);
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
protected override void OnPointerPressed(PointerPressedEventArgs e)
|
||||
{
|
||||
UpdatePointer(e);
|
||||
e.Pointer.Capture(this);
|
||||
e.Handled = true;
|
||||
base.OnPointerPressed(e);
|
||||
}
|
||||
|
||||
protected override void OnPointerMoved(PointerEventArgs e)
|
||||
{
|
||||
UpdatePointer(e);
|
||||
e.Handled = true;
|
||||
base.OnPointerMoved(e);
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
{
|
||||
_pointers.Remove(e.Pointer);
|
||||
e.Handled = true;
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
protected override void OnPointerCaptureLost(PointerCaptureLostEventArgs e)
|
||||
{
|
||||
_pointers.Remove(e.Pointer);
|
||||
InvalidateVisual();
|
||||
}
|
||||
|
||||
public override void Render(DrawingContext context)
|
||||
{
|
||||
context.FillRectangle(Brushes.Transparent, new Rect(default, Bounds.Size));
|
||||
foreach (var pt in _pointers.Values)
|
||||
{
|
||||
var brush = new ImmutableSolidColorBrush(pt.Color);
|
||||
context.DrawGeometry(brush, null, new EllipseGeometry(new Rect(pt.Point.X - 75, pt.Point.Y - 75,
|
||||
150, 150)));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -22,7 +22,10 @@ namespace ControlCatalog.Pages
|
|||
public override void Render(DrawingContext context)
|
||||
{
|
||||
base.Render(context);
|
||||
Window w = (Window)VisualRoot;
|
||||
if (!(VisualRoot is Window w))
|
||||
{
|
||||
return;
|
||||
}
|
||||
var screens = w.Screens.All;
|
||||
var scaling = ((IRenderRoot)w).RenderScaling;
|
||||
|
||||
|
@ -54,12 +57,15 @@ namespace ControlCatalog.Pages
|
|||
|
||||
text.Text = $"WorkArea: {screen.WorkingArea.Width}:{screen.WorkingArea.Height}";
|
||||
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 20), text);
|
||||
|
||||
text.Text = $"Primary: {screen.Primary}";
|
||||
|
||||
text.Text = $"Scaling: {screen.PixelDensity * 100}%";
|
||||
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 40), text);
|
||||
|
||||
text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
|
||||
text.Text = $"Primary: {screen.Primary}";
|
||||
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 60), text);
|
||||
|
||||
text.Text = $"Current: {screen.Equals(w.Screens.ScreenFromBounds(new PixelRect(w.Position, PixelSize.FromSize(w.Bounds.Size, scaling))))}";
|
||||
context.DrawText(Brushes.Black, boundsRect.Position.WithY(boundsRect.Size.Height + 80), text);
|
||||
}
|
||||
|
||||
context.DrawRectangle(p, new Rect(w.Position.X / 10f + Math.Abs(_leftMost), w.Position.Y / 10, w.Bounds.Width / 10, w.Bounds.Height / 10));
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
<UserControl xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
x:Class="ControlCatalog.Pages.TabStripPage"
|
||||
xmlns="https://github.com/avaloniaui">
|
||||
<StackPanel Orientation="Vertical" Spacing="4">
|
||||
<TextBlock Classes="h1">TabStrip</TextBlock>
|
||||
<TextBlock Classes="h2">A control which displays a selectable strip of tabs</TextBlock>
|
||||
|
||||
<Separator Margin="0 16"/>
|
||||
|
||||
<TextBlock Classes="h1">Defined in XAML</TextBlock>
|
||||
<TabStrip>
|
||||
<TabStripItem>Item 1</TabStripItem>
|
||||
<TabStripItem>Item 2</TabStripItem>
|
||||
<TabStripItem IsEnabled="False">Disabled</TabStripItem>
|
||||
</TabStrip>
|
||||
|
||||
<Separator Margin="0 16"/>
|
||||
|
||||
<TextBlock Classes="h1">Dynamically generated</TextBlock>
|
||||
<TabStrip Items="{Binding}">
|
||||
<TabStrip.Styles>
|
||||
<Style Selector="TabStripItem">
|
||||
<Setter Property="IsEnabled" Value="{Binding IsEnabled}"/>
|
||||
</Style>
|
||||
</TabStrip.Styles>
|
||||
<TabStrip.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Header}"/>
|
||||
</DataTemplate>
|
||||
</TabStrip.ItemTemplate>
|
||||
</TabStrip>
|
||||
</StackPanel>
|
||||
</UserControl>
|
|
@ -0,0 +1,45 @@
|
|||
using System;
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Avalonia.Media.Imaging;
|
||||
using Avalonia.Platform;
|
||||
|
||||
namespace ControlCatalog.Pages
|
||||
{
|
||||
public class TabStripPage : UserControl
|
||||
{
|
||||
public TabStripPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
DataContext = new[]
|
||||
{
|
||||
new TabStripItemViewModel
|
||||
{
|
||||
Header = "Item 1",
|
||||
},
|
||||
new TabStripItemViewModel
|
||||
{
|
||||
Header = "Item 2",
|
||||
},
|
||||
new TabStripItemViewModel
|
||||
{
|
||||
Header = "Disabled",
|
||||
IsEnabled = false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
private class TabStripItemViewModel
|
||||
{
|
||||
public string Header { get; set; }
|
||||
public bool IsEnabled { get; set; } = true;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,6 +26,10 @@
|
|||
<TextBox Width="200" Text="Left aligned text" TextAlignment="Left" />
|
||||
<TextBox Width="200" Text="Center aligned text" TextAlignment="Center" />
|
||||
<TextBox Width="200" Text="Right aligned text" TextAlignment="Right" />
|
||||
<TextBox Width="200" Text="Custom selection brush"
|
||||
SelectionStart="5" SelectionEnd="22"
|
||||
SelectionBrush="Green" SelectionForegroundBrush="Yellow"/>
|
||||
<TextBox Width="200" Text="Custom caret brush" CaretBrush="DarkOrange"/>
|
||||
</StackPanel>
|
||||
|
||||
<StackPanel Orientation="Vertical" Spacing="8">
|
||||
|
|
|
@ -6,16 +6,29 @@
|
|||
<TextBlock Classes="h2">Displays a hierachical tree of data.</TextBlock>
|
||||
|
||||
<StackPanel Orientation="Horizontal"
|
||||
Margin="0,16,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
Spacing="16">
|
||||
<TreeView SelectionMode="Multiple" Items="{Binding}" Width="250" Height="350">
|
||||
<TreeView.ItemTemplate>
|
||||
<TreeDataTemplate ItemsSource="{Binding Children}">
|
||||
<TextBlock Text="{Binding Header}"/>
|
||||
</TreeDataTemplate>
|
||||
</TreeView.ItemTemplate>
|
||||
</TreeView>
|
||||
Margin="0,16,0,0"
|
||||
HorizontalAlignment="Center"
|
||||
Spacing="16">
|
||||
<StackPanel Orientation="Vertical" Spacing="8">
|
||||
<TreeView Items="{Binding Items}" SelectedItems="{Binding SelectedItems}" SelectionMode="{Binding SelectionMode}" Width="250" Height="350">
|
||||
<TreeView.ItemTemplate>
|
||||
<TreeDataTemplate ItemsSource="{Binding Children}">
|
||||
<TextBlock Text="{Binding Header}"/>
|
||||
</TreeDataTemplate>
|
||||
</TreeView.ItemTemplate>
|
||||
</TreeView>
|
||||
|
||||
<Button Command="{Binding AddItemCommand}">Add</Button>
|
||||
|
||||
<Button Command="{Binding RemoveItemCommand}">Remove</Button>
|
||||
|
||||
<ComboBox SelectedIndex="{Binding SelectionMode, Mode=TwoWay}">
|
||||
<ComboBoxItem>Single</ComboBoxItem>
|
||||
<ComboBoxItem>Multiple</ComboBoxItem>
|
||||
<ComboBoxItem>Toggle</ComboBoxItem>
|
||||
<ComboBoxItem>AlwaysSelected</ComboBoxItem>
|
||||
</ComboBox>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using System.Reactive;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace ControlCatalog.Pages
|
||||
{
|
||||
|
@ -10,8 +11,8 @@ namespace ControlCatalog.Pages
|
|||
{
|
||||
public TreeViewPage()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
DataContext = new Node().Children;
|
||||
InitializeComponent();
|
||||
DataContext = new PageViewModel();
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
|
@ -19,22 +20,96 @@ namespace ControlCatalog.Pages
|
|||
AvaloniaXamlLoader.Load(this);
|
||||
}
|
||||
|
||||
public class Node
|
||||
private class PageViewModel : ReactiveObject
|
||||
{
|
||||
private IList<Node> _children;
|
||||
private SelectionMode _selectionMode;
|
||||
|
||||
public PageViewModel()
|
||||
{
|
||||
Node root = new Node();
|
||||
Items = root.Children;
|
||||
SelectedItems = new ObservableCollection<Node>();
|
||||
|
||||
AddItemCommand = ReactiveCommand.Create(() =>
|
||||
{
|
||||
Node parentItem = SelectedItems.Count > 0 ? SelectedItems[0] : root;
|
||||
parentItem.AddNewItem();
|
||||
});
|
||||
|
||||
RemoveItemCommand = ReactiveCommand.Create(() =>
|
||||
{
|
||||
while (SelectedItems.Count > 0)
|
||||
{
|
||||
Node lastItem = SelectedItems[0];
|
||||
RecursiveRemove(Items, lastItem);
|
||||
SelectedItems.Remove(lastItem);
|
||||
}
|
||||
|
||||
bool RecursiveRemove(ObservableCollection<Node> items, Node selectedItem)
|
||||
{
|
||||
if (items.Remove(selectedItem))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
foreach (Node item in items)
|
||||
{
|
||||
if (item.AreChildrenInitialized && RecursiveRemove(item.Children, selectedItem))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public ObservableCollection<Node> Items { get; }
|
||||
|
||||
public ObservableCollection<Node> SelectedItems { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> AddItemCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> RemoveItemCommand { get; }
|
||||
|
||||
public SelectionMode SelectionMode
|
||||
{
|
||||
get => _selectionMode;
|
||||
set
|
||||
{
|
||||
SelectedItems.Clear();
|
||||
this.RaiseAndSetIfChanged(ref _selectionMode, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class Node
|
||||
{
|
||||
private int _counter;
|
||||
private ObservableCollection<Node> _children;
|
||||
|
||||
public string Header { get; private set; }
|
||||
public IList<Node> Children
|
||||
|
||||
public bool AreChildrenInitialized => _children != null;
|
||||
|
||||
public ObservableCollection<Node> Children
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_children == null)
|
||||
{
|
||||
_children = Enumerable.Range(1, 10).Select(i => new Node() {Header = $"Item {i}"})
|
||||
.ToArray();
|
||||
_children = new ObservableCollection<Node>(Enumerable.Range(1, 10).Select(i => CreateNewNode()));
|
||||
}
|
||||
return _children;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddNewItem() => Children.Add(CreateNewNode());
|
||||
|
||||
public override string ToString() => Header;
|
||||
|
||||
private Node CreateNewNode() => new Node {Header = $"Item {_counter++}"};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,23 +24,28 @@
|
|||
Name="PART_ScrollViewer"
|
||||
HorizontalScrollBarVisibility="{TemplateBinding (ScrollViewer.HorizontalScrollBarVisibility)}"
|
||||
VerticalScrollBarVisibility="{TemplateBinding (ScrollViewer.VerticalScrollBarVisibility)}"
|
||||
Background="{TemplateBinding Background}">
|
||||
Background="{TemplateBinding Background}"
|
||||
DockPanel.Dock="Left">
|
||||
<ItemsPresenter
|
||||
Name="PART_ItemsPresenter"
|
||||
Items="{TemplateBinding Items}"
|
||||
ItemsPanel="{TemplateBinding ItemsPanel}"
|
||||
ItemTemplate="{TemplateBinding ItemTemplate}"
|
||||
MemberSelector="{TemplateBinding MemberSelector}">
|
||||
ItemTemplate="{TemplateBinding ItemTemplate}">
|
||||
</ItemsPresenter>
|
||||
</ScrollViewer>
|
||||
<ContentPresenter
|
||||
Name="PART_SelectedContentHost"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding SelectedContent}"
|
||||
ContentTemplate="{TemplateBinding SelectedContentTemplate}">
|
||||
</ContentPresenter>
|
||||
<ContentControl Content="{TemplateBinding Tag}" HorizontalContentAlignment="Right" DockPanel.Dock="Bottom"/>
|
||||
<ScrollViewer
|
||||
HorizontalScrollBarVisibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem.(ScrollViewer.HorizontalScrollBarVisibility)}"
|
||||
VerticalScrollBarVisibility="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=SelectedItem.(ScrollViewer.VerticalScrollBarVisibility)}">
|
||||
<ContentPresenter
|
||||
Name="PART_SelectedContentHost"
|
||||
Margin="{TemplateBinding Padding}"
|
||||
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
|
||||
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
|
||||
Content="{TemplateBinding SelectedContent}"
|
||||
ContentTemplate="{TemplateBinding SelectedContentTemplate}">
|
||||
</ContentPresenter>
|
||||
</ScrollViewer>
|
||||
</DockPanel>
|
||||
</Border>
|
||||
</ControlTemplate>
|
||||
|
@ -59,6 +64,8 @@
|
|||
<DoubleTransition Property="Opacity" Duration="0:0:0.150"/>
|
||||
</Transitions>
|
||||
</Setter>
|
||||
<Setter Property="(ScrollViewer.HorizontalScrollBarVisibility)" Value="Auto"/>
|
||||
<Setter Property="(ScrollViewer.VerticalScrollBarVisibility)" Value="Auto"/>
|
||||
</Style>
|
||||
<Style Selector="TabControl.sidebar > TabItem:pointerover">
|
||||
<Setter Property="Opacity" Value="1"/>
|
||||
|
|
|
@ -2,12 +2,14 @@
|
|||
using System.Reactive;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.VisualTree;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace ControlCatalog.ViewModels
|
||||
{
|
||||
public class ContextMenuPageViewModel
|
||||
{
|
||||
public Control View { get; set; }
|
||||
public ContextMenuPageViewModel()
|
||||
{
|
||||
OpenCommand = ReactiveCommand.CreateFromTask(Open);
|
||||
|
@ -48,8 +50,11 @@ namespace ControlCatalog.ViewModels
|
|||
|
||||
public async Task Open()
|
||||
{
|
||||
var window = View?.GetVisualRoot() as Window;
|
||||
if (window == null)
|
||||
return;
|
||||
var dialog = new OpenFileDialog();
|
||||
var result = await dialog.ShowAsync(App.Current.MainWindow);
|
||||
var result = await dialog.ShowAsync(window);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace ControlCatalog.ViewModels
|
||||
{
|
||||
public class ItemsRepeaterPageViewModel : ReactiveObject
|
||||
{
|
||||
private int _newItemIndex = 1;
|
||||
private int _newGenerationIndex = 0;
|
||||
private ObservableCollection<Item> _items;
|
||||
|
||||
public ItemsRepeaterPageViewModel()
|
||||
{
|
||||
Items = CreateItems();
|
||||
}
|
||||
|
||||
public ObservableCollection<Item> Items
|
||||
{
|
||||
get => _items;
|
||||
set => this.RaiseAndSetIfChanged(ref _items, value);
|
||||
}
|
||||
|
||||
public Item SelectedItem { get; set; }
|
||||
|
||||
public void AddItem()
|
||||
{
|
||||
var index = SelectedItem != null ? Items.IndexOf(SelectedItem) : -1;
|
||||
Items.Insert(index + 1, new Item { Text = $"New Item {_newItemIndex++}" });
|
||||
}
|
||||
|
||||
public void RandomizeHeights()
|
||||
{
|
||||
var random = new Random();
|
||||
|
||||
foreach (var i in Items)
|
||||
{
|
||||
i.Height = random.Next(240) + 10;
|
||||
}
|
||||
}
|
||||
|
||||
public void ResetItems()
|
||||
{
|
||||
Items = CreateItems();
|
||||
}
|
||||
|
||||
private ObservableCollection<Item> CreateItems()
|
||||
{
|
||||
var suffix = _newGenerationIndex == 0 ? string.Empty : $"[{_newGenerationIndex.ToString()}]";
|
||||
|
||||
_newGenerationIndex++;
|
||||
|
||||
return new ObservableCollection<Item>(
|
||||
Enumerable.Range(1, 100000).Select(i => new Item
|
||||
{
|
||||
Text = $"Item {i.ToString()} {suffix}"
|
||||
}));
|
||||
}
|
||||
|
||||
public class Item : ReactiveObject
|
||||
{
|
||||
private double _height = double.NaN;
|
||||
|
||||
public string Text { get; set; }
|
||||
|
||||
public double Height
|
||||
{
|
||||
get => _height;
|
||||
set => this.RaiseAndSetIfChanged(ref _height, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,12 @@
|
|||
using System.Reactive;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Controls.Notifications;
|
||||
using Avalonia.Diagnostics.ViewModels;
|
||||
using Avalonia.Dialogs;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace ControlCatalog.ViewModels
|
||||
{
|
||||
class MainWindowViewModel : ViewModelBase
|
||||
class MainWindowViewModel : ReactiveObject
|
||||
{
|
||||
private IManagedNotificationManager _notificationManager;
|
||||
|
||||
|
@ -27,6 +28,20 @@ namespace ControlCatalog.ViewModels
|
|||
{
|
||||
NotificationManager.Show(new Avalonia.Controls.Notifications.Notification("Error", "Native Notifications are not quite ready. Coming soon.", NotificationType.Error));
|
||||
});
|
||||
|
||||
AboutCommand = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
var dialog = new AboutAvaloniaDialog();
|
||||
|
||||
var mainWindow = (App.Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime)?.MainWindow;
|
||||
|
||||
await dialog.ShowDialog(mainWindow);
|
||||
});
|
||||
|
||||
ExitCommand = ReactiveCommand.Create(() =>
|
||||
{
|
||||
(App.Current.ApplicationLifetime as IClassicDesktopStyleApplicationLifetime).Shutdown();
|
||||
});
|
||||
}
|
||||
|
||||
public IManagedNotificationManager NotificationManager
|
||||
|
@ -40,5 +55,9 @@ namespace ControlCatalog.ViewModels
|
|||
public ReactiveCommand<Unit, Unit> ShowManagedNotificationCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> ShowNativeNotificationCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> AboutCommand { get; }
|
||||
|
||||
public ReactiveCommand<Unit, Unit> ExitCommand { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
using System.Collections.Generic;
|
||||
using System.Reactive;
|
||||
using System.Reactive.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.VisualTree;
|
||||
using ReactiveUI;
|
||||
|
||||
namespace ControlCatalog.ViewModels
|
||||
{
|
||||
public class MenuPageViewModel
|
||||
{
|
||||
public Control View { get; set; }
|
||||
public MenuPageViewModel()
|
||||
{
|
||||
OpenCommand = ReactiveCommand.CreateFromTask(Open);
|
||||
SaveCommand = ReactiveCommand.Create(Save);
|
||||
SaveCommand = ReactiveCommand.Create(Save, Observable.Return(false));
|
||||
OpenRecentCommand = ReactiveCommand.Create<string>(OpenRecent);
|
||||
|
||||
MenuItems = new[]
|
||||
|
@ -64,8 +67,11 @@ namespace ControlCatalog.ViewModels
|
|||
|
||||
public async Task Open()
|
||||
{
|
||||
var window = View?.GetVisualRoot() as Window;
|
||||
if (window == null)
|
||||
return;
|
||||
var dialog = new OpenFileDialog();
|
||||
var result = await dialog.ShowAsync(App.Current.MainWindow);
|
||||
var result = await dialog.ShowAsync(window);
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
|
|
12
NuGet.Config
12
NuGet.Config
|
@ -1,15 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageRestore>
|
||||
<add key="enabled" value="True" />
|
||||
<add key="automatic" value="True" />
|
||||
</packageRestore>
|
||||
<packageSources>
|
||||
<add key="NuGet 3 (plain)" value="http://api.nuget.org/v3/index.json" />
|
||||
<add key="Avalonia Nightly" value="https://www.myget.org/F/avalonia-ci/api/v2" />
|
||||
<add key="Avalonia PR" value="https://www.myget.org/F/avalonia-prs/api/v3/index.json" />
|
||||
<clear />
|
||||
<add key="api.nuget.org" value="https://api.nuget.org/v3/index.json" />
|
||||
</packageSources>
|
||||
<bindingRedirects>
|
||||
<add key="skip" value="False" />
|
||||
</bindingRedirects>
|
||||
</configuration>
|
||||
|
|
Loading…
Reference in New Issue