diff --git a/.github/workflows/pull-requests.yml b/.github/workflows/pull-requests.yml index d61621f0..68ae04db 100644 --- a/.github/workflows/pull-requests.yml +++ b/.github/workflows/pull-requests.yml @@ -11,11 +11,11 @@ concurrency: jobs: build: - runs-on: macos-14 + runs-on: macos-15 steps: - name: xCode - run: sudo xcode-select -s /Applications/Xcode_16.1.app/Contents/Developer/ + run: sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer/ - uses: actions/checkout@v4 @@ -23,7 +23,7 @@ jobs: uses: actions/setup-dotnet@v4 with: dotnet-version: | - 8.x.x + 10.x.x - name: Install workloads run: dotnet workload restore src/Avalonia.FuncUI.sln diff --git a/global.json b/global.json index 683b612c..4524fb32 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,6 @@ { "sdk": { - "version": "8.0.400", + "version": "10.0.100", "rollForward": "minor" } } \ No newline at end of file diff --git a/src/Avalonia.FuncUI.ControlCatalog/Avalonia.FuncUI.ControlCatalog.Browser/Avalonia.FuncUI.ControlCatalog.Browser.fsproj b/src/Avalonia.FuncUI.ControlCatalog/Avalonia.FuncUI.ControlCatalog.Browser/Avalonia.FuncUI.ControlCatalog.Browser.fsproj index ab82074e..4506f739 100644 --- a/src/Avalonia.FuncUI.ControlCatalog/Avalonia.FuncUI.ControlCatalog.Browser/Avalonia.FuncUI.ControlCatalog.Browser.fsproj +++ b/src/Avalonia.FuncUI.ControlCatalog/Avalonia.FuncUI.ControlCatalog.Browser/Avalonia.FuncUI.ControlCatalog.Browser.fsproj @@ -1,6 +1,6 @@  - net8.0-browser + net10.0-browser browser-wasm wwwroot\main.js ./_framework diff --git a/src/Avalonia.FuncUI.ControlCatalog/Avalonia.FuncUI.ControlCatalog/Views/Tabs/DragDropDemo.fs b/src/Avalonia.FuncUI.ControlCatalog/Avalonia.FuncUI.ControlCatalog/Views/Tabs/DragDropDemo.fs index 5d6df6f7..5aafc968 100644 --- a/src/Avalonia.FuncUI.ControlCatalog/Avalonia.FuncUI.ControlCatalog/Views/Tabs/DragDropDemo.fs +++ b/src/Avalonia.FuncUI.ControlCatalog/Avalonia.FuncUI.ControlCatalog/Views/Tabs/DragDropDemo.fs @@ -28,11 +28,11 @@ module DragDropDemo = let doDrag (e, dragCount) = async { - let dragData = DataObject() - dragData.Set(DataFormats.Text, $"You have dragged text %d{dragCount} times") + use dragData = new DataTransfer() + dragData.Add(DataTransferItem.Create(DataFormat.Text, $"You have dragged text %d{dragCount} times")) let! result = Dispatcher.UIThread.InvokeAsync - (fun _ -> DragDrop.DoDragDrop(e, dragData, DragDropEffects.Copy)) |> Async.AwaitTask + (fun _ -> DragDrop.DoDragDropAsync(e, dragData, DragDropEffects.Copy)) |> Async.AwaitTask return match result with | DragDropEffects.Copy -> "The text was copied" | DragDropEffects.Link -> "The text was linked" @@ -83,19 +83,19 @@ module DragDropDemo = (TextBlock.create [ TextBlock.text state.dropText Control.onDrop (fun e -> - if e.Data.Contains(DataFormats.Text) then - Dropped(e.Data.GetText()) |> dispatch - elif e.Data.Contains(DataFormats.Files) then + if e.DataTransfer.Contains(DataFormat.Text) then + Dropped(e.DataTransfer.TryGetText()) |> dispatch + elif e.DataTransfer.Contains(DataFormat.File) then Dropped - (e.Data.GetFiles() + (e.DataTransfer.TryGetFiles() |> Seq.map (fun item -> item.Name) |> String.concat Environment.NewLine) |> dispatch ) Control.onDragOver (fun e -> e.DragEffects <- - if e.Data.Contains(DataFormats.Text) - || e.Data.Contains(DataFormats.Files) then + if e.DataTransfer.Contains(DataFormat.Text) + || e.DataTransfer.Contains(DataFormat.File) then e.DragEffects &&& (DragDropEffects.Copy ||| DragDropEffects.Link) else diff --git a/src/Avalonia.FuncUI.Diagnostics/Views/Views.StateHookViews.fs b/src/Avalonia.FuncUI.Diagnostics/Views/Views.StateHookViews.fs index dfd4b22b..3ad11fe2 100644 --- a/src/Avalonia.FuncUI.Diagnostics/Views/Views.StateHookViews.fs +++ b/src/Avalonia.FuncUI.Diagnostics/Views/Views.StateHookViews.fs @@ -6,6 +6,7 @@ open Avalonia open Avalonia.Controls open Avalonia.FuncUI.DSL open Avalonia.FuncUI.Types +open Avalonia.Input.Platform open Avalonia.Layout open Avalonia.Media diff --git a/src/Avalonia.FuncUI/Avalonia.FuncUI.fsproj b/src/Avalonia.FuncUI/Avalonia.FuncUI.fsproj index c9a1eeed..2e2792d6 100644 --- a/src/Avalonia.FuncUI/Avalonia.FuncUI.fsproj +++ b/src/Avalonia.FuncUI/Avalonia.FuncUI.fsproj @@ -134,7 +134,7 @@ - + diff --git a/src/Avalonia.FuncUI/DSL/AutoCompleteBox.fs b/src/Avalonia.FuncUI/DSL/AutoCompleteBox.fs index 69456f4f..2b773285 100644 --- a/src/Avalonia.FuncUI/DSL/AutoCompleteBox.fs +++ b/src/Avalonia.FuncUI/DSL/AutoCompleteBox.fs @@ -46,12 +46,8 @@ module AutoCompleteBox = static member isDropDownOpen<'t when 't :> AutoCompleteBox>(value: bool) : IAttr<'t> = AttrBuilder<'t>.CreateProperty(AutoCompleteBox.IsDropDownOpenProperty, value, ValueNone) - static member valueMemberBinding<'t when 't :> AutoCompleteBox>(binding: IBinding) : IAttr<'t> = - let name = nameof Unchecked.defaultof<'t>.ValueMemberBinding - let getter: 't -> IBinding = (fun control -> control.ValueMemberBinding) - let setter: 't * IBinding -> unit = (fun (control, value) -> control.ValueMemberBinding <- value) - - AttrBuilder<'t>.CreateProperty(name, binding, ValueSome getter, ValueSome setter, ValueNone) + static member valueMemberBinding<'t when 't :> AutoCompleteBox>(binding: BindingBase) : IAttr<'t> = + AttrBuilder<'t>.CreateProperty<_>(AutoCompleteBox.ValueMemberBindingProperty, binding, ValueNone) static member selectedItem<'t when 't :> AutoCompleteBox>(value: obj) : IAttr<'t> = AttrBuilder<'t>.CreateProperty(AutoCompleteBox.SelectedItemProperty, value, ValueNone) @@ -166,4 +162,5 @@ module AutoCompleteBox = AttrBuilder<'t>.CreateProperty(AutoCompleteBox.ItemsSourceProperty, items, ValueNone) static member asyncPopulator<'t when 't :> AutoCompleteBox>(populator: Func>>) : IAttr<'t> = - AttrBuilder<'t>.CreateProperty<_>(AutoCompleteBox.AsyncPopulatorProperty, populator, ValueNone) \ No newline at end of file + AttrBuilder<'t>.CreateProperty<_>(AutoCompleteBox.AsyncPopulatorProperty, populator, ValueNone) + diff --git a/src/Avalonia.FuncUI/DSL/BindingEvaluator.fs b/src/Avalonia.FuncUI/DSL/BindingEvaluator.fs deleted file mode 100644 index f48f0aa9..00000000 --- a/src/Avalonia.FuncUI/DSL/BindingEvaluator.fs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Avalonia.FuncUI.DSL - -open Avalonia -open Avalonia.Controls -open Avalonia.Data - -[] -module BindingEvaluator = - open Avalonia.FuncUI.Types - open Avalonia.FuncUI.Builder - - let create<'x> - (attrs: IAttr> list) - : IView> = - ViewBuilder.Create>(attrs) - - let createWith<'x> - (binding: IBinding) - (attrs: IAttr> list) - : IView> = - create attrs |> View.withConstructorArgs [| binding |] - - type AutoCompleteBox.BindingEvaluator<'x> with - - static member value<'t, 'x when 't :> AutoCompleteBox.BindingEvaluator<'x>>(value: 'x) : IAttr<'t> = - let prop: StyledProperty<'x> = AutoCompleteBox.BindingEvaluator.ValueProperty - AttrBuilder<'t>.CreateProperty<'x>(prop, value, ValueNone) - - static member valueBinding<'t, 'x when 't :> AutoCompleteBox.BindingEvaluator<'x>> - (value: IBinding) - : IAttr<'t> = - let name = nameof Unchecked.defaultof<'t>.ValueBinding - let getter: 't -> IBinding = fun x -> x.ValueBinding - let setter: 't * IBinding -> unit = fun (x, v) -> x.ValueBinding <- v - - AttrBuilder<'t>.CreateProperty(name, value, ValueSome getter, ValueSome setter, ValueNone) diff --git a/src/Avalonia.FuncUI/DSL/Buttons/RadioButton.fs b/src/Avalonia.FuncUI/DSL/Buttons/RadioButton.fs index 5aff2745..04fcc066 100644 --- a/src/Avalonia.FuncUI/DSL/Buttons/RadioButton.fs +++ b/src/Avalonia.FuncUI/DSL/Buttons/RadioButton.fs @@ -5,6 +5,7 @@ module RadioButton = open Avalonia.Controls open Avalonia.FuncUI.Types open Avalonia.FuncUI.Builder + open Avalonia.Interactivity let create (attrs: IAttr list): IView = ViewBuilder.Create(attrs) @@ -13,4 +14,13 @@ module RadioButton = static member groupName<'t when 't :> RadioButton>(value: string) : IAttr<'t> = AttrBuilder<'t>.CreateProperty(RadioButton.GroupNameProperty, value, ValueNone) - \ No newline at end of file + + static member onChecked<'t when 't :> RadioButton>(func: RoutedEventArgs -> unit, ?subPatchOptions) : IAttr<'t> = + + let onCheckedHandler (args: RoutedEventArgs) = + match args.Source with + | :? RadioButton as selection when selection.IsChecked.GetValueOrDefault() = true -> + func(args) + | _ -> () + + AttrBuilder<'t>.CreateSubscription(RadioButton.IsCheckedChangedEvent, onCheckedHandler, ?subPatchOptions = subPatchOptions) \ No newline at end of file diff --git a/src/Avalonia.FuncUI/DSL/Buttons/ToggleButton.fs b/src/Avalonia.FuncUI/DSL/Buttons/ToggleButton.fs index 6a9464b9..4915004f 100644 --- a/src/Avalonia.FuncUI/DSL/Buttons/ToggleButton.fs +++ b/src/Avalonia.FuncUI/DSL/Buttons/ToggleButton.fs @@ -26,15 +26,3 @@ module ToggleButton = static member onIsCheckedChanged<'t when 't :> ToggleButton>(func: RoutedEventArgs -> unit, ?subPatchOptions) : IAttr<'t> = AttrBuilder<'t>.CreateSubscription(ToggleButton.IsCheckedChangedEvent, func, ?subPatchOptions = subPatchOptions) - - [] - static member onChecked<'t when 't :> ToggleButton>(func: RoutedEventArgs -> unit, ?subPatchOptions) : IAttr<'t> = - AttrBuilder<'t>.CreateSubscription(ToggleButton.CheckedEvent, func, ?subPatchOptions = subPatchOptions) - - [] - static member onUnchecked<'t when 't :> ToggleButton>(func: RoutedEventArgs -> unit, ?subPatchOptions) : IAttr<'t> = - AttrBuilder<'t>.CreateSubscription(ToggleButton.UncheckedEvent, func, ?subPatchOptions = subPatchOptions) - - [] - static member onIndeterminate<'t when 't :> ToggleButton>(func : RoutedEventArgs -> unit, ?subPatchOptions) : IAttr<'t> = - AttrBuilder<'t>.CreateSubscription(ToggleButton.IndeterminateEvent, func, ?subPatchOptions = subPatchOptions) \ No newline at end of file diff --git a/src/Avalonia.FuncUI/DSL/DataGrid.fs b/src/Avalonia.FuncUI/DSL/DataGrid.fs index d21142be..d0b6af11 100644 --- a/src/Avalonia.FuncUI/DSL/DataGrid.fs +++ b/src/Avalonia.FuncUI/DSL/DataGrid.fs @@ -105,8 +105,8 @@ module DataGridBoundColumn = type DataGridBoundColumn with - static member binding<'t when 't :> DataGridBoundColumn>(binding: IBinding) : IAttr<'t> = - AttrBuilder<'t>.CreateProperty( + static member binding<'t when 't :> DataGridBoundColumn>(binding: BindingBase) : IAttr<'t> = + AttrBuilder<'t>.CreateProperty( name = "Binding", value = binding, getter = ValueSome (fun column -> column.Binding), @@ -114,8 +114,8 @@ module DataGridBoundColumn = comparer = ValueNone ) - static member clipboardContentBinding<'t when 't :> DataGridBoundColumn>(binding: IBinding) : IAttr<'t> = - AttrBuilder<'t>.CreateProperty( + static member clipboardContentBinding<'t when 't :> DataGridBoundColumn>(binding: BindingBase) : IAttr<'t> = + AttrBuilder<'t>.CreateProperty( name = "ClipboardContentBinding", value = binding, getter = ValueSome (fun column -> column.ClipboardContentBinding), diff --git a/src/Avalonia.FuncUI/DSL/ItemsControl.fs b/src/Avalonia.FuncUI/DSL/ItemsControl.fs index be89a74b..5a7e26ac 100644 --- a/src/Avalonia.FuncUI/DSL/ItemsControl.fs +++ b/src/Avalonia.FuncUI/DSL/ItemsControl.fs @@ -20,8 +20,8 @@ module ItemsControl = type ItemsControl with - static member displayMemberBinding<'t when 't :> ItemsControl>(value: IBinding) : IAttr<'t> = - AttrBuilder<'t>.CreateProperty(ItemsControl.DisplayMemberBindingProperty, value, ValueNone) + static member displayMemberBinding<'t when 't :> ItemsControl>(value: BindingBase) : IAttr<'t> = + AttrBuilder<'t>.CreateProperty(ItemsControl.DisplayMemberBindingProperty, value, ValueNone) static member viewItems<'t when 't :> ItemsControl>(views: IView list) : IAttr<'t> = let getter : ('t -> obj) = (fun control -> control.Items :> obj) diff --git a/src/Avalonia.FuncUI/DSL/Primitives/Popup.fs b/src/Avalonia.FuncUI/DSL/Primitives/Popup.fs index 5f5f7844..6590d04a 100644 --- a/src/Avalonia.FuncUI/DSL/Primitives/Popup.fs +++ b/src/Avalonia.FuncUI/DSL/Primitives/Popup.fs @@ -88,11 +88,6 @@ module Popup = static member placementRect<'t when 't :> Popup>(value: Rect option) : IAttr<'t> = value |> Option.toNullable |> Popup.placementRect - - [] - static member placementMode<'t when 't :> Popup>(value: PlacementMode) : IAttr<'t> = - AttrBuilder<'t>.CreateProperty(Popup.PlacementModeProperty, value, ValueNone) - static member placementTarget<'t when 't :> Popup>(value: Control) : IAttr<'t> = AttrBuilder<'t>.CreateProperty(Popup.PlacementTargetProperty, value, ValueNone) diff --git a/src/Avalonia.FuncUI/DSL/Primitives/SelectingItemsControl.fs b/src/Avalonia.FuncUI/DSL/Primitives/SelectingItemsControl.fs index 1cf7668c..8d74ae95 100644 --- a/src/Avalonia.FuncUI/DSL/Primitives/SelectingItemsControl.fs +++ b/src/Avalonia.FuncUI/DSL/Primitives/SelectingItemsControl.fs @@ -30,8 +30,8 @@ module SelectingItemsControl = static member selectedItem<'t when 't :> SelectingItemsControl>(item: obj) : IAttr<'t> = AttrBuilder<'t>.CreateProperty(SelectingItemsControl.SelectedItemProperty, item, ValueNone) - static member selectedValueBinding<'t when 't :> SelectingItemsControl>(binding: IBinding) : IAttr<'t> = - AttrBuilder<'t>.CreateProperty(SelectingItemsControl.SelectedValueBindingProperty, binding, ValueNone) + static member selectedValueBinding<'t when 't :> SelectingItemsControl>(binding: BindingBase) : IAttr<'t> = + AttrBuilder<'t>.CreateProperty(SelectingItemsControl.SelectedValueBindingProperty, binding, ValueNone) static member selectedValue<'t when 't :> SelectingItemsControl>(value: obj) : IAttr<'t> = AttrBuilder<'t>.CreateProperty(SelectingItemsControl.SelectedValueProperty, value, ValueNone) diff --git a/src/Avalonia.FuncUI/DataTemplateView.fs b/src/Avalonia.FuncUI/DataTemplateView.fs index 12bc987b..bdb8a3c5 100644 --- a/src/Avalonia.FuncUI/DataTemplateView.fs +++ b/src/Avalonia.FuncUI/DataTemplateView.fs @@ -32,13 +32,15 @@ type DataTemplateView<'data, 'childData, 'view when 'view :> IView> (this.ViewFunc.GetType(), this.SupportsRecycling).GetHashCode() interface ITreeDataTemplate with - member this.ItemsSelector (item: obj) : InstancedBinding = + // member this.ItemsSelector (item: obj) : InstancedBinding = + member this.BindChildren(target: AvaloniaObject, targetProperty: AvaloniaProperty, item) : IDisposable = match this.ItemsSource with | ValueNone -> null | ValueSome expression -> match item with | :? 'data as data -> - InstancedBinding.OneTime(expression.Invoke(data)) + target.SetCurrentValue(targetProperty, expression.Invoke(data)) + { new IDisposable with member this.Dispose() = () } | _ -> null member this.Match (data: obj) : bool = diff --git a/src/Directory.Build.props b/src/Directory.Build.props index bac967ca..615774a0 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -1,6 +1,7 @@ - 11.3.0 + 12.0.0-preview1 + 11.3.12 1.5.2 diff --git a/src/Examples/Elmish/Examples.Elmish.MusicPlayer/Examples.Elmish.MusicPlayer.fsproj b/src/Examples/Elmish/Examples.Elmish.MusicPlayer/Examples.Elmish.MusicPlayer.fsproj index 48b35350..3f2442e0 100644 --- a/src/Examples/Elmish/Examples.Elmish.MusicPlayer/Examples.Elmish.MusicPlayer.fsproj +++ b/src/Examples/Elmish/Examples.Elmish.MusicPlayer/Examples.Elmish.MusicPlayer.fsproj @@ -28,7 +28,7 @@ - + diff --git a/src/Examples/Elmish/Examples.Elmish.Presso/Main.fs b/src/Examples/Elmish/Examples.Elmish.Presso/Main.fs index 89a85818..5024f42b 100644 --- a/src/Examples/Elmish/Examples.Elmish.Presso/Main.fs +++ b/src/Examples/Elmish/Examples.Elmish.Presso/Main.fs @@ -1,8 +1,5 @@ namespace Examples.Presso -open Avalonia.Controls.Shapes -open Avalonia.Media - module Main = open Avalonia.Controls open Avalonia.Controls.Primitives diff --git a/src/Examples/Examples.DataGridPlayground/Program.fs b/src/Examples/Examples.DataGridPlayground/Program.fs index 4534ae89..c67555e8 100644 --- a/src/Examples/Examples.DataGridPlayground/Program.fs +++ b/src/Examples/Examples.DataGridPlayground/Program.fs @@ -52,7 +52,7 @@ type Views = DataGrid.columns [ DataGridTextColumn.create [ DataGridTextColumn.header "Name" - DataGridTextColumn.binding (Binding ("Name", BindingMode.TwoWay)) + DataGridTextColumn.binding (ReflectionBinding ("Name", Mode = BindingMode.TwoWay)) DataGridTextColumn.width (DataGridLength(2, DataGridLengthUnitType.Star)) ] DataGridTemplateColumn.create [ @@ -68,7 +68,7 @@ type Views = DataTemplateView<_>.create (fun (data: Person) -> TextBox.create [ TextBox.init (fun t -> - t.Bind(TextBox.TextProperty, Binding("Name", BindingMode.TwoWay)) |> ignore + t.Bind(TextBox.TextProperty, ReflectionBinding("Name", Mode = BindingMode.TwoWay)) |> ignore ) ] ) diff --git a/src/Examples/Examples.Mobile.iOS/Examples.Mobile.iOS.fsproj b/src/Examples/Examples.Mobile.iOS/Examples.Mobile.iOS.fsproj index d0d440f0..943a3485 100644 --- a/src/Examples/Examples.Mobile.iOS/Examples.Mobile.iOS.fsproj +++ b/src/Examples/Examples.Mobile.iOS/Examples.Mobile.iOS.fsproj @@ -3,7 +3,7 @@ Exe manual - net8.0-ios + net10.0-ios 13.0 diff --git a/src/NuGet.config b/src/NuGet.config index 940a8416..00b95b48 100644 --- a/src/NuGet.config +++ b/src/NuGet.config @@ -2,5 +2,7 @@ + + \ No newline at end of file