英文:
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<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 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
替换为以下内容的Grid
或StackLayout
:
<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>
<Grid Padding="2"
>
<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="40"
CornerRadius="5"
BackgroundColor="{Binding ColorToPrint}">
<Label Text="{Binding Id}"
TextColor="Black"
FontAttributes="Bold"
FontSize="15"
HorizontalOptions="Center"
VerticalOptions="Center"
/>
</Frame>>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
请注意,这里只是将原始代码部分翻译成中文。
英文:
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:
<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>
<Grid Padding="2"
>
<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="40"
CornerRadius="5"
BackgroundColor="{Binding ColorToPrint}">
<Label Text="{Binding Id}"
TextColor="Black"
FontAttributes="Bold"
FontSize="15"
HorizontalOptions="Center"
VerticalOptions="Center"
/>
</Frame>
</Grid>
</DataTemplate>
</CollectionView.ItemTemplate>
</CollectionView>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论