How does one dynamically update the Border Stroke/Bg color of each CollectionView item individually (without refreshing page)?

Daniel Donnelly, Jr 86 Reputation points
2023-04-19T21:46:26.1866667+00:00

Currently my DevliceListView looks like this:

<?xml version="1.0" encoding="UTF-8" ?>
<ContentView x:Class="CEDDashboard.View.DeviceList"
             xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:model="clr-namespace:CEDDashboard.Model"
             xmlns:viewmodel="clr-namespace:CEDDashboard.ViewModel"
             x:DataType="viewmodel:DeviceListViewModel"
             xmlns:local="clr-namespace:CEDDashboard">
    <ContentView.Content>
        <CollectionView
            ItemsSource="{Binding Devices}"
            SelectionMode="Single"
            SelectedItem="{Binding SelectedDevice}">
            
            <CollectionView.EmptyView>
                <StackLayout Padding="100">
                    <Image
                        HorizontalOptions="Center"
                        HeightRequest="160"
                        WidthRequest="160"
                        Source="nodata.png"
                        VerticalOptions="Center" />
                </StackLayout>
            </CollectionView.EmptyView>

            <CollectionView.ItemsLayout>
                <GridItemsLayout  Orientation="Vertical" Span="2" />
            </CollectionView.ItemsLayout>

            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="model:Device">
                    <Grid Padding="10" HorizontalOptions="FillAndExpand">
                        <Border HeightRequest="140" Style="{StaticResource CardView}"
                                StrokeShape="RoundRectangle 16">
                            <Border.GestureRecognizers>
                                <TapGestureRecognizer x:Name="avatarTapGesture"
                                    Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:DeviceListViewModel}}, Path=GoToDetailsCommand}"
                                    CommandParameter="{Binding .}"
                                    NumberOfTapsRequired="2"/>
                                <TapGestureRecognizer x:Name="avatarSelectTapGesture"
                                    Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:DeviceListViewModel}}, Path=SelectDeviceCommand}"
                                    CommandParameter="{Binding .}"
                                    NumberOfTapsRequired="1"/>
                            </Border.GestureRecognizers>
                            <Grid Padding="0" ColumnDefinitions="128,*" HorizontalOptions="FillAndExpand">
                                <Border Style="{StaticResource CardView}"
                                        Stroke="{Binding Status, Converter={StaticResource deviceToStatusColor}}"
                                        BackgroundColor="{Binding Status, Converter={StaticResource deviceToStatusColor}}"
                                        StrokeShape="RoundRectangle 64"
                                        StrokeThickness="7"
                                        WidthRequest="128"
                                        HeightRequest="128"
                                        Grid.Column="0">
                                    <Image
                                        Aspect="AspectFill"
                                        Source="{Binding Image}" />
                                </Border>
                                <VerticalStackLayout
                                    HorizontalOptions="Fill"
                                    VerticalOptions="Center"
                                    Grid.Column="1"
                                    Padding="10">
                                    <Label Style="{StaticResource LargeLabel}" Text="{Binding Name}"
                                           HorizontalOptions="StartAndExpand"/>
                                </VerticalStackLayout>
                            </Grid>
                        </Border>
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </ContentView.Content>
</ContentView>

As you can see I'm using a converter to take a Device, grab its Status (connected / not connected) string and convert it to Red for not connected and Green for connected.

My question is, how can I, in a IDispatchTimer in DeviceListViewModel's timeout action update the Stroke / Bg colors of that inner Border without refreshing the entire page that holds a DeviceList content view.

I've spent two days on this. It shouldn't be this difficult! But a las it is... Anyway. Thanks for any guidance!

.NET MAUI
.NET MAUI
A Microsoft open-source framework for building native device applications spanning mobile, tablet, and desktop.
2,976 questions
{count} votes

Accepted answer
  1. Leon Lu (Shanghai Wicresoft Co,.Ltd.) 69,386 Reputation points Microsoft Vendor
    2023-04-20T06:18:12.5633333+00:00

    Hello, Do you add INotifyPropertyChanged inteferface for your model? For example, I create a model that called Device.cs, I need to implement INotifyPropertyChanged interface, then achieve get/set method like following code.

    public class Device: INotifyPropertyChanged
    {
        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
       public event PropertyChangedEventHandler PropertyChanged;
       private string _status;
       public string Status
        {
            set
            {
                if (_status != value)
                {
                    _status = value;
                    OnPropertyChanged("Status");
               }
            }
            get
            {
                return _status;
            }
        }
       public string Image { get; set; }
       public string Name { get; set; }
    }
    

    If you change the value of Status changed, deviceToStatusColor converter will be executed. If you have implemented INotifyPropertyChanged interface, could you minimize code to just what is needed to reproduce the problem? Such as ViewModel class and Model class. Best Regards, Leon Lu


    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment". Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    1 person found this answer helpful.

0 additional answers

Sort by: Most helpful