Xamarin – CollectionView绑定到ObservableCollection问题

huangapple go评论54阅读模式
英文:

Xamarin - CollectionView bind on ObservableCollection issue

问题

I'm experiencing a really strange issue trying to print an observableCollection of object in a CollectionView. I want to have a grid of 42 blocks, and in each one print a number from 1 to 42. When I click on a block, I want its background to turn green.

Here is my code (pretty simple) :

Model :

public class Case
{
    public int Id { get; set; }
    public string ColorToPrint { get; set; }

    public Case(int id, string color)
    {
        Id = id;
        ColorToPrint = color;
    }
}

ViewModel :

public ICommand SelectionChangedCommand { get; set; }
public GridViewModel() 
{
    Cases = new ObservableCollection<Case>();
    for (int i=1; i<=42; i++)
    {
        Case c = new Case(i, "Grey");
        Cases.Add(c);
    }

    SelectionChangedCommand = new Command(OnSelectionChanged);

}

private void OnSelectionChanged()
{
    Case c = new Case(SelectedCase.Id, "Green");
    Cases[SelectedCase.Id - 1] = c;
}

private ObservableCollection<Case> cases;
public ObservableCollection<Case> Cases
{
    get => cases;
    set
    {
        cases = value;
        OnPropertyChanged(nameof(Cases));
    }
}

private Case selectedCase;
public Case SelectedCase
{
    get => selectedCase;
    set
    {
        selectedCase = value;
        OnPropertyChanged(nameof(SelectedCase));
    }
}

And my page :

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>

    <CollectionView ItemsSource="{Binding Cases}"
                        SelectionMode="Single"
                        SelectedItem="{Binding SelectedCase}"
                        SelectionChangedCommand="{Binding SelectionChangedCommand}"
                        Grid.Column="0"
                        Grid.Row="0"
                        ItemsLayout="VerticalGrid, 6"
                        Margin="20">
        <CollectionView.ItemTemplate>
            <DataTemplate>
                
                <Frame Padding="2"
                       BackgroundColor="Transparent">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup Name="CommonStates">
                            <VisualState Name="Normal" />
                            <VisualState Name="Selected">
                                <VisualState.Setters>
                                    <Setter Property="BackgroundColor" Value="Transparent"/>
                                </VisualState.Setters>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Frame BorderColor="Black"
                            MinimumHeightRequest="20"
                            CornerRadius="5"
                            BackgroundColor="{Binding ColorToPrint}">
                        <Label Text="{Binding Id}"
                               TextColor="Black"
                               FontAttributes="Bold"
                               FontSize="15"
                               HorizontalOptions="Center"
                               VerticalOptions="Center"
                               />
                    </Frame>
                    
                </Frame>
            </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
</Grid>

Of course, on my page.cs, the viewmodel is defined as the bindingContext.

So this code is working pretty well but I got a strange behavior erasing the number in a block if I click on it (color change well) and reappearing if I click on another block. It seems also that this behavior is happening randomly and not all the time.

I've been looking for a solution for my entire afternoon and I would really appreciate a bit of help on that.

Thanks, everyone, and excuse my pretty bad English.

英文:

I'm experiencing a really strange issue trying to print an observableCollection of object in a CollectionView. I want to have a grid of 42 block and in each one print a number from 1 to 42. When I click on a block, I want its background to turn green.

Here is my code (pretty simple) :

Model :

public class Case
    {
        public int Id { get; set; }
        public string ColorToPrint { get; set; }

        public Case(int id, string color)
        {
            Id = id;
            ColorToPrint = color;
        }
    }

ViewModel :

public ICommand SelectionChangedCommand { get; set; }
        public GridViewModel() 
        {
            Cases = new ObservableCollection&lt;Case&gt;();
            for (int i=1; i&lt;=42; i++)
            {
                Case c = new Case(i, &quot;Grey&quot;);
                Cases.Add(c);
            }

            SelectionChangedCommand = new Command(OnSelectionChanged);

        }

        private void OnSelectionChanged()
        {
            Case c = new Case(SelectedCase.Id, &quot;Green&quot;);
            Cases[SelectedCase.Id - 1] = c;
        }

        private ObservableCollection&lt;Case&gt; cases;
        public ObservableCollection&lt;Case&gt; Cases
        {
            get =&gt; cases;
            set
            {
                cases = value;
                OnPropertyChanged(nameof(Cases));
            }
        }

        private Case selectedCase;
        public Case SelectedCase
        {
            get =&gt; selectedCase;
            set
            {
                selectedCase = value;
                OnPropertyChanged(nameof(SelectedCase));
            }
        }
    }

And my page :

&lt;Grid&gt;
        &lt;Grid.RowDefinitions&gt;
            &lt;RowDefinition Height=&quot;*&quot;/&gt;
        &lt;/Grid.RowDefinitions&gt;

        &lt;CollectionView ItemsSource=&quot;{Binding Cases}&quot;
                            SelectionMode=&quot;Single&quot;
                            SelectedItem=&quot;{Binding SelectedCase}&quot;
                            SelectionChangedCommand=&quot;{Binding SelectionChangedCommand}&quot;
                            Grid.Column=&quot;0&quot;
                            Grid.Row=&quot;0&quot;
                            ItemsLayout=&quot;VerticalGrid, 6&quot;
                            Margin=&quot;20&quot;&gt;
            &lt;CollectionView.ItemTemplate&gt;
                &lt;DataTemplate&gt;
                    
                    &lt;Frame Padding=&quot;2&quot;
                           BackgroundColor=&quot;Transparent&quot;&gt;
                        &lt;VisualStateManager.VisualStateGroups&gt;
                            &lt;VisualStateGroup Name=&quot;CommonStates&quot;&gt;
                                &lt;VisualState Name=&quot;Normal&quot; /&gt;
                                &lt;VisualState Name=&quot;Selected&quot;&gt;
                                    &lt;VisualState.Setters&gt;
                                        &lt;Setter Property=&quot;BackgroundColor&quot; Value=&quot;Transparent&quot;/&gt;
                                    &lt;/VisualState.Setters&gt;
                                &lt;/VisualState&gt;
                            &lt;/VisualStateGroup&gt;
                        &lt;/VisualStateManager.VisualStateGroups&gt;
                        &lt;Frame BorderColor=&quot;Black&quot;
                                MinimumHeightRequest=&quot;20&quot;
                                CornerRadius=&quot;5&quot;
                                BackgroundColor=&quot;{Binding ColorToPrint}&quot;&gt;
                            &lt;Label Text=&quot;{Binding Id}&quot;
                                   TextColor=&quot;Black&quot;
                                   FontAttributes=&quot;Bold&quot;
                                   FontSize=&quot;15&quot;
                                   HorizontalOptions=&quot;Center&quot;
                                   VerticalOptions=&quot;Center&quot;
                                   /&gt;
                        &lt;/Frame&gt;
                        
                    &lt;/Frame&gt;
                &lt;/DataTemplate&gt;
                &lt;/CollectionView.ItemTemplate&gt;
            &lt;/CollectionView&gt;
    &lt;/Grid&gt;

Of course, on my page.cs the viewmodel is define as the bindingContext.

So this code is working pretty well but I got a strange behaviour erasing the number in a block if I click on it (color change well) and reapearing if I click on another block. It seems also that this behaviour is happing ramdomly and not all time.

I've been lokking for a solution for my entire afternoon and I would really appreciate a bit of help on that.

Thanks everyone and excuse my pretty bad english ..

Tried different way of updating my observablecollection and also a lot of things with the propertychange event

答案1

得分: 0

这个问题可以在我的一侧复制。要解决此问题,您可以将CollectionView中项目的外部Frame替换为以下内容的GridStackLayout

&lt;CollectionView ItemsSource=&quot;{Binding Cases}&quot; 
                SelectionMode=&quot;Single&quot;
                SelectedItem=&quot;{Binding SelectedCase}&quot;
                SelectionChangedCommand=&quot;{Binding SelectionChangedCommand}&quot;
                Grid.Column=&quot;0&quot;
                Grid.Row=&quot;0&quot;
                               
                ItemsLayout=&quot;VerticalGrid, 6&quot;
                Margin=&quot;20&quot;&gt;
    &lt;CollectionView.ItemTemplate&gt;
        &lt;DataTemplate&gt;

            &lt;Grid Padding=&quot;2&quot;
               &gt;
                &lt;VisualStateManager.VisualStateGroups&gt;
                    &lt;VisualStateGroup Name=&quot;CommonStates&quot;&gt;
                        &lt;VisualState Name=&quot;Normal&quot; /&gt;
                        &lt;VisualState Name=&quot;Selected&quot;&gt;
                            &lt;VisualState.Setters&gt;
                                &lt;Setter Property=&quot;BackgroundColor&quot; Value=&quot;Transparent&quot;/&gt;
                            &lt;/VisualState.Setters&gt;
                        &lt;/VisualState&gt;
                    &lt;/VisualStateGroup&gt;
                &lt;/VisualStateManager.VisualStateGroups&gt;
                
                &lt;Frame BorderColor=&quot;Black&quot;
                    MinimumHeightRequest=&quot;40&quot;
                    CornerRadius=&quot;5&quot;
                    BackgroundColor=&quot;{Binding ColorToPrint}&quot;&gt;
                    &lt;Label Text=&quot;{Binding Id}&quot;
                       TextColor=&quot;Black&quot;
                       FontAttributes=&quot;Bold&quot;
                       FontSize=&quot;15&quot;
                       HorizontalOptions=&quot;Center&quot;
                       VerticalOptions=&quot;Center&quot;
                       /&gt;
                &lt;/Frame&gt>
             
            &lt;/Grid&gt;
        &lt;/DataTemplate&gt;
    &lt;/CollectionView.ItemTemplate&gt;
&lt;/CollectionView&gt;

请注意,这里只是将原始代码部分翻译成中文。

英文:

This issue can be replicated on my side. To fix the issue, you can replace the outside Frame of the items in CollectionView with Grid or StackLayout like below:


            &lt;CollectionView ItemsSource=&quot;{Binding Cases}&quot; 
                            SelectionMode=&quot;Single&quot;
                            SelectedItem=&quot;{Binding SelectedCase}&quot;
                            SelectionChangedCommand=&quot;{Binding SelectionChangedCommand}&quot;
                            Grid.Column=&quot;0&quot;
                            Grid.Row=&quot;0&quot;
                                                       
                            ItemsLayout=&quot;VerticalGrid, 6&quot;
                            Margin=&quot;20&quot;&gt;
                &lt;CollectionView.ItemTemplate&gt;
                    &lt;DataTemplate&gt;

                        &lt;Grid Padding=&quot;2&quot;
                           &gt;
                            &lt;VisualStateManager.VisualStateGroups&gt;
                                &lt;VisualStateGroup Name=&quot;CommonStates&quot;&gt;
                                    &lt;VisualState Name=&quot;Normal&quot; /&gt;
                                    &lt;VisualState Name=&quot;Selected&quot;&gt;
                                        &lt;VisualState.Setters&gt;
                                            &lt;Setter Property=&quot;BackgroundColor&quot; Value=&quot;Transparent&quot;/&gt;
                                        &lt;/VisualState.Setters&gt;
                                    &lt;/VisualState&gt;
                                &lt;/VisualStateGroup&gt;
                            &lt;/VisualStateManager.VisualStateGroups&gt;
                            
                            &lt;Frame BorderColor=&quot;Black&quot;
                                MinimumHeightRequest=&quot;40&quot;
                                CornerRadius=&quot;5&quot;
                                BackgroundColor=&quot;{Binding ColorToPrint}&quot;&gt;
                                &lt;Label Text=&quot;{Binding Id}&quot;
                                   TextColor=&quot;Black&quot;
                                   FontAttributes=&quot;Bold&quot;
                                   FontSize=&quot;15&quot;
                                   HorizontalOptions=&quot;Center&quot;
                                   VerticalOptions=&quot;Center&quot;
                                   /&gt;
                            &lt;/Frame&gt;
                         
                        &lt;/Grid&gt;
                    &lt;/DataTemplate&gt;
                &lt;/CollectionView.ItemTemplate&gt;
            &lt;/CollectionView&gt;

huangapple
  • 本文由 发表于 2023年4月17日 02:21:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/76029579.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定