Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Windows] Fixed VisualState Update for CollectionView SelectedItem #25145

Merged
merged 4 commits into from
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ void UpdatePlatformSelection()
break;
}

UpdateItemContentControlSelection();
_ignorePlatformSelectionChange = false;
}

Expand Down Expand Up @@ -160,13 +161,7 @@ void UpdateVirtualSelection()
break;
}

var formsItemContentControls = ListViewBase.GetChildren<ItemContentControl>();

foreach (var formsItemContentControl in formsItemContentControls)
{
bool isSelected = ItemsView.SelectedItem == formsItemContentControl.FormsDataContext || ItemsView.SelectedItems.Contains(formsItemContentControl.FormsDataContext);
formsItemContentControl.UpdateIsSelected(isSelected);
}
UpdateItemContentControlSelection();
}

void UpdateVirtualSingleSelection()
Expand Down Expand Up @@ -245,6 +240,17 @@ public object ConvertBack(object value, Type targetType, object parameter, strin
return SelectionMode.None;
}
}

void UpdateItemContentControlSelection()
{
var formsItemContentControls = ListViewBase.GetChildren<ItemContentControl>();

foreach (var formsItemContentControl in formsItemContentControls)
{
bool isSelected = ItemsView.SelectedItem == formsItemContentControl.FormsDataContext || ItemsView.SelectedItems.Contains(formsItemContentControl.FormsDataContext);
formsItemContentControl.UpdateIsSelected(isSelected);
}
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
59 changes: 59 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue22104.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:Maui.Controls.Sample.Issues"
x:Class="Maui.Controls.Sample.Issues.Issue22104">

<ContentPage.BindingContext>
<local:Issue22104ViewModel/>
</ContentPage.BindingContext>

<ContentPage.Resources>
<Style TargetType="Label">
<Setter Property="VisualStateManager.VisualStateGroups">
<VisualStateGroupList>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<VisualState.Setters>
<Setter Property="TextColor" Value="Black"/>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Selected">
<VisualState.Setters>
<Setter Property="TextColor" Value="Red"/>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateGroupList>
</Setter>
</Style>
</ContentPage.Resources>

<VerticalStackLayout
Padding="30,0"
Spacing="25">
<Image
Source="dotnet_bot.png"
HeightRequest="185"
Aspect="AspectFit"
SemanticProperties.Description="dot net bot in a race car number eight" />

<Button AutomationId="Button"
Text="Select Next"
Command="{Binding SelectNextCommand}"
HorizontalOptions="Fill" />

<Label
Text="{Binding LabelText}" />

<CollectionView AutomationId="CollectionView" ItemsSource="{Binding List}"
SelectionMode="Single"
SelectedItem="{Binding SelectedItem}">
<CollectionView.ItemTemplate>
<DataTemplate x:DataType="x:String">
<Label Text="{Binding .}"/>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
</VerticalStackLayout>
</ContentPage>
116 changes: 116 additions & 0 deletions src/Controls/tests/TestCases.HostApp/Issues/Issue22104.xaml.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using Microsoft.Maui.Controls.Internals;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Windows.Input;

namespace Maui.Controls.Sample.Issues;

[XamlCompilation(XamlCompilationOptions.Compile)]
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 22104, "VisualState Setters not working properly on Windows for a CollectionView", PlatformAffected.UWP)]
public partial class Issue22104 : ContentPage
{
public Issue22104()
{
InitializeComponent();
}
}

internal class Issue22104ViewModel : INotifyPropertyChanged
{
// Observable Collection for the List
public ObservableCollection<string> List { get; set; } = new() { "One", "Two", "Three", "Four", "Five" };

private string _selectedItem;
public string SelectedItem
{
get => _selectedItem;
set
{
if (_selectedItem != value)
{
_selectedItem = value;
OnPropertyChanged(nameof(SelectedItem));
}
}
}

private string _labelText;
public string LabelText
{
get => _labelText;
set
{
if (_labelText != value)
{
_labelText = value;
OnPropertyChanged(nameof(LabelText));
}
}
}

private int _selectedIndex;

public Issue22104ViewModel()
{
// Initialize the SelectNextCommand
SelectNextCommand = new RelayCommand(SelectNext);
}

// Command for selecting the next item
public ICommand SelectNextCommand { get; }

private async Task SelectNext()
{
await MainThread.InvokeOnMainThreadAsync(() =>
{
if (SelectedItem == null)
{
_selectedIndex = 0;
}
else
{
_selectedIndex++;
}

if (_selectedIndex < List.Count)
{
SelectedItem = List[_selectedIndex];
}
else
{
SelectedItem = null;
}

LabelText = SelectedItem;
});
}

// INotifyPropertyChanged implementation
public event PropertyChangedEventHandler PropertyChanged;

protected virtual void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}

public class RelayCommand : ICommand
{
private readonly Func<Task> execute;
private readonly Func<bool> canExecute;

public RelayCommand(Func<Task> execute, Func<bool> canExecute = null)
{
this.execute = execute ?? throw new ArgumentNullException(nameof(execute));
this.canExecute = canExecute;
}

public event EventHandler CanExecuteChanged;

public bool CanExecute(object parameter) => canExecute == null || canExecute();

public async void Execute(object parameter) => await execute();

public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using NUnit.Framework;
using UITest.Appium;
using UITest.Core;

namespace Microsoft.Maui.TestCases.Tests.Issues
{
public class Issue22104 : _IssuesUITest
{
public Issue22104(TestDevice testDevice) : base(testDevice)
{
}

public override string Issue => "VisualState Setters not working properly on Windows for a CollectionView";

[Test]
[Category(UITestCategories.CollectionView)]
[FailsOnMac]
public void VerifyCollectionViewVisualState()
{
App.WaitForElement("CollectionView");
App.Tap("Button");
VerifyScreenshot();
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading