Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -449,3 +449,4 @@ src/Tools/
# MSBuild generator editor configs
**/*.GeneratedMSBuildEditorConfig.editorconfig
/app
.dotnet/
2 changes: 2 additions & 0 deletions src/ReactiveUI.Maui/ReactiveEntryCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using Microsoft.Maui.Controls;

namespace ReactiveUI.Maui;
Expand All @@ -17,6 +18,7 @@ namespace ReactiveUI.Maui;
[RequiresDynamicCode("ReactiveEntryCell uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("ReactiveEntryCell uses methods that may require unreferenced code")]
#endif
[Obsolete("ListView and its cells are obsolete in .NET MAUI, please use CollectionView with a DataTemplate and a ReactiveContentView-based view instead. This will be removed in a future release.")]
public partial class ReactiveEntryCell<TViewModel> : EntryCell, IViewFor<TViewModel>
where TViewModel : class
{
Expand Down
2 changes: 2 additions & 0 deletions src/ReactiveUI.Maui/ReactiveImageCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using Microsoft.Maui.Controls;

namespace ReactiveUI.Maui;
Expand All @@ -17,6 +18,7 @@ namespace ReactiveUI.Maui;
[RequiresDynamicCode("ReactiveImageCell uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("ReactiveImageCell uses methods that may require unreferenced code")]
#endif
[Obsolete("ListView and its cells are obsolete in .NET MAUI, please use CollectionView with a DataTemplate and a ReactiveContentView-based view instead. This will be removed in a future release.")]
public partial class ReactiveImageCell<TViewModel> : ImageCell, IViewFor<TViewModel>
where TViewModel : class
{
Expand Down
171 changes: 171 additions & 0 deletions src/ReactiveUI.Maui/ReactiveImageItemView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;

namespace ReactiveUI.Maui;

/// <summary>
/// A <see cref="ReactiveContentView{TViewModel}"/> that displays an image with text content similar to an ImageCell,
/// but designed for use with CollectionView and DataTemplates. This serves as a modern replacement
/// for ReactiveImageCell which relied on the deprecated ListView.
/// </summary>
/// <typeparam name="TViewModel">The type of the view model.</typeparam>
/// <seealso cref="ReactiveContentView{TViewModel}" />
#if NET6_0_OR_GREATER
[RequiresDynamicCode("ReactiveImageItemView uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("ReactiveImageItemView uses methods that may require unreferenced code")]
#endif
public partial class ReactiveImageItemView<TViewModel> : ReactiveContentView<TViewModel>
where TViewModel : class
{
/// <summary>
/// The image source bindable property.
/// </summary>
public static readonly BindableProperty ImageSourceProperty = BindableProperty.Create(
nameof(ImageSource),
typeof(ImageSource),
typeof(ReactiveImageItemView<TViewModel>),
default(ImageSource));

/// <summary>
/// The text bindable property for the primary text.
/// </summary>
public static readonly BindableProperty TextProperty = BindableProperty.Create(
nameof(Text),
typeof(string),
typeof(ReactiveImageItemView<TViewModel>),
default(string));

/// <summary>
/// The detail bindable property for the secondary text.
/// </summary>
public static readonly BindableProperty DetailProperty = BindableProperty.Create(
nameof(Detail),
typeof(string),
typeof(ReactiveImageItemView<TViewModel>),
default(string));

/// <summary>
/// The text color bindable property.
/// </summary>
public static readonly BindableProperty TextColorProperty = BindableProperty.Create(
nameof(TextColor),
typeof(Color),
typeof(ReactiveImageItemView<TViewModel>),
default(Color));

/// <summary>
/// The detail color bindable property.
/// </summary>
public static readonly BindableProperty DetailColorProperty = BindableProperty.Create(
nameof(DetailColor),
typeof(Color),
typeof(ReactiveImageItemView<TViewModel>),
default(Color));

private readonly Image _image;
private readonly Label _textLabel;
private readonly Label _detailLabel;

/// <summary>
/// Initializes a new instance of the <see cref="ReactiveImageItemView{TViewModel}"/> class.
/// </summary>
public ReactiveImageItemView()
{
_image = new Image
{
WidthRequest = 40,
HeightRequest = 40,
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Start
};

_textLabel = new Label
{
FontSize = 16,
VerticalOptions = LayoutOptions.Center
};

_detailLabel = new Label
{
FontSize = 12,
VerticalOptions = LayoutOptions.Center,
Opacity = 0.7
};

var textStackLayout = new StackLayout
{
Orientation = StackOrientation.Vertical,
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.Fill,
Children = { _textLabel, _detailLabel }
};

var mainStackLayout = new StackLayout
{
Orientation = StackOrientation.Horizontal,
VerticalOptions = LayoutOptions.Center,
Padding = 16,
Spacing = 12,
Children = { _image, textStackLayout }
};

Content = mainStackLayout;

// Bind the control properties to the bindable properties
_image.SetBinding(Image.SourceProperty, new Binding(nameof(ImageSource), source: this));
_textLabel.SetBinding(Label.TextProperty, new Binding(nameof(Text), source: this));
_textLabel.SetBinding(Label.TextColorProperty, new Binding(nameof(TextColor), source: this));
_detailLabel.SetBinding(Label.TextProperty, new Binding(nameof(Detail), source: this));
_detailLabel.SetBinding(Label.TextColorProperty, new Binding(nameof(DetailColor), source: this));
}

/// <summary>
/// Gets or sets the image source to display.
/// </summary>
public ImageSource? ImageSource
{
get => (ImageSource?)GetValue(ImageSourceProperty);
set => SetValue(ImageSourceProperty, value);
}

/// <summary>
/// Gets or sets the primary text to display.
/// </summary>
public string? Text
{
get => (string?)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}

/// <summary>
/// Gets or sets the detail text to display.
/// </summary>
public string? Detail
{
get => (string?)GetValue(DetailProperty);
set => SetValue(DetailProperty, value);
}

/// <summary>
/// Gets or sets the color of the primary text.
/// </summary>
public Color TextColor
{
get => (Color)GetValue(TextColorProperty);
set => SetValue(TextColorProperty, value);
}

/// <summary>
/// Gets or sets the color of the detail text.
/// </summary>
public Color DetailColor
{
get => (Color)GetValue(DetailColorProperty);
set => SetValue(DetailColorProperty, value);
}
}
2 changes: 2 additions & 0 deletions src/ReactiveUI.Maui/ReactiveSwitchCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using Microsoft.Maui.Controls;

namespace ReactiveUI.Maui;
Expand All @@ -17,6 +18,7 @@ namespace ReactiveUI.Maui;
[RequiresDynamicCode("ReactiveSwitchCell uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("ReactiveSwitchCell uses methods that may require unreferenced code")]
#endif
[Obsolete("ListView and its cells are obsolete in .NET MAUI, please use CollectionView with a DataTemplate and a ReactiveContentView-based view instead. This will be removed in a future release.")]
public partial class ReactiveSwitchCell<TViewModel> : SwitchCell, IViewFor<TViewModel>
where TViewModel : class
{
Expand Down
2 changes: 2 additions & 0 deletions src/ReactiveUI.Maui/ReactiveTextCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using Microsoft.Maui.Controls;

namespace ReactiveUI.Maui;
Expand All @@ -17,6 +18,7 @@ namespace ReactiveUI.Maui;
[RequiresDynamicCode("ReactiveTextCell uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("ReactiveTextCell uses methods that may require unreferenced code")]
#endif
[Obsolete("ListView and its cells are obsolete in .NET MAUI, please use CollectionView with a DataTemplate and a ReactiveContentView-based view instead. This will be removed in a future release.")]
public partial class ReactiveTextCell<TViewModel> : TextCell, IViewFor<TViewModel>
where TViewModel : class
{
Expand Down
134 changes: 134 additions & 0 deletions src/ReactiveUI.Maui/ReactiveTextItemView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// Copyright (c) 2025 .NET Foundation and Contributors. All rights reserved.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;

namespace ReactiveUI.Maui;

/// <summary>
/// A <see cref="ReactiveContentView{TViewModel}"/> that displays text content similar to a TextCell,
/// but designed for use with CollectionView and DataTemplates. This serves as a modern replacement
/// for ReactiveTextCell which relied on the deprecated ListView.
/// </summary>
/// <typeparam name="TViewModel">The type of the view model.</typeparam>
/// <seealso cref="ReactiveContentView{TViewModel}" />
#if NET6_0_OR_GREATER
[RequiresDynamicCode("ReactiveTextItemView uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("ReactiveTextItemView uses methods that may require unreferenced code")]
#endif
public partial class ReactiveTextItemView<TViewModel> : ReactiveContentView<TViewModel>
where TViewModel : class
{
/// <summary>
/// The text bindable property for the primary text.
/// </summary>
public static readonly BindableProperty TextProperty = BindableProperty.Create(
nameof(Text),
typeof(string),
typeof(ReactiveTextItemView<TViewModel>),
default(string));

/// <summary>
/// The detail bindable property for the secondary text.
/// </summary>
public static readonly BindableProperty DetailProperty = BindableProperty.Create(
nameof(Detail),
typeof(string),
typeof(ReactiveTextItemView<TViewModel>),
default(string));

/// <summary>
/// The text color bindable property.
/// </summary>
public static readonly BindableProperty TextColorProperty = BindableProperty.Create(
nameof(TextColor),
typeof(Color),
typeof(ReactiveTextItemView<TViewModel>),
default(Color));

/// <summary>
/// The detail color bindable property.
/// </summary>
public static readonly BindableProperty DetailColorProperty = BindableProperty.Create(
nameof(DetailColor),
typeof(Color),
typeof(ReactiveTextItemView<TViewModel>),
default(Color));

private readonly Label _textLabel;
private readonly Label _detailLabel;

/// <summary>
/// Initializes a new instance of the <see cref="ReactiveTextItemView{TViewModel}"/> class.
/// </summary>
public ReactiveTextItemView()
{
_textLabel = new Label
{
FontSize = 16,
VerticalOptions = LayoutOptions.Center
};

_detailLabel = new Label
{
FontSize = 12,
VerticalOptions = LayoutOptions.Center,
Opacity = 0.7
};

var stackLayout = new StackLayout
{
Orientation = StackOrientation.Vertical,
VerticalOptions = LayoutOptions.Center,
Padding = 16,
Children = { _textLabel, _detailLabel }
};

Content = stackLayout;

// Bind the label properties to the bindable properties
_textLabel.SetBinding(Label.TextProperty, new Binding(nameof(Text), source: this));
_textLabel.SetBinding(Label.TextColorProperty, new Binding(nameof(TextColor), source: this));
_detailLabel.SetBinding(Label.TextProperty, new Binding(nameof(Detail), source: this));
_detailLabel.SetBinding(Label.TextColorProperty, new Binding(nameof(DetailColor), source: this));
}

/// <summary>
/// Gets or sets the primary text to display.
/// </summary>
public string? Text
{
get => (string?)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}

/// <summary>
/// Gets or sets the detail text to display.
/// </summary>
public string? Detail
{
get => (string?)GetValue(DetailProperty);
set => SetValue(DetailProperty, value);
}

/// <summary>
/// Gets or sets the color of the primary text.
/// </summary>
public Color TextColor
{
get => (Color)GetValue(TextColorProperty);
set => SetValue(TextColorProperty, value);
}

/// <summary>
/// Gets or sets the color of the detail text.
/// </summary>
public Color DetailColor
{
get => (Color)GetValue(DetailColorProperty);
set => SetValue(DetailColorProperty, value);
}
}
2 changes: 2 additions & 0 deletions src/ReactiveUI.Maui/ReactiveViewCell.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for full license information.

using System;
using Microsoft.Maui.Controls;

namespace ReactiveUI.Maui;
Expand All @@ -17,6 +18,7 @@ namespace ReactiveUI.Maui;
[RequiresDynamicCode("ReactiveViewCell uses methods that require dynamic code generation")]
[RequiresUnreferencedCode("ReactiveViewCell uses methods that may require unreferenced code")]
#endif
[Obsolete("ListView and its cells are obsolete in .NET MAUI, please use CollectionView with a DataTemplate and a ReactiveContentView-based view instead. This will be removed in a future release.")]
public partial class ReactiveViewCell<TViewModel> : ViewCell, IViewFor<TViewModel>
where TViewModel : class
{
Expand Down
Loading